ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilObjUserFolderGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
23 use ILIAS\User\Profile\Prompt\Repository as PromptRepository;
31 
41 {
43 
45  'visible' => 'user_visible_in_profile',
46  'changeable' => 'changeable',
47  'searchable' => 'header_searchable',
48  'required' => 'required_field',
49  'export' => 'export',
50  'course_export' => 'course_export',
51  'group_export' => 'group_export',
52  'prg_export' => 'prg_export',
53  'visib_reg' => 'header_visible_registration',
54  'visib_lua' => 'usr_settings_visib_lua',
55  'changeable_lua' => 'usr_settings_changeable_lua'
56  ];
57 
58  private ilPropertyFormGUI $form;
59  private array $requested_ids; // Missing array type.
60  private string $selected_action;
62  private int $user_owner_id = 0;
63  private int $confirm_change = 0;
64  private ilDBInterface $db;
65  private ilLogger $log;
67  private bool $usrFieldChangeListenersAccepted = false;
68 
73  private DIContainer $dic;
74 
78 
79  public function __construct(
80  $a_data,
81  int $a_id,
82  bool $a_call_by_reference
83  ) {
84  global $DIC;
85  $this->dic = $DIC;
86 
87  $this->event = $DIC['ilAppEventHandler'];
88  $this->filesystem = $DIC->filesystem()->storage();
89  $this->upload = $DIC['upload'];
90  $this->db = $DIC['ilDB'];
91  $this->dic->upload();
92 
93  $this->type = 'usrf';
95  $a_data,
96  $a_id,
97  $a_call_by_reference,
98  false
99  );
100 
101  $this->lng->loadLanguageModule('search');
102  $this->lng->loadLanguageModule('user');
103  $this->lng->loadLanguageModule('tos');
104  $this->ctrl->saveParameter(
105  $this,
106  'letter'
107  );
108 
109  $this->user_request = new UserGUIRequest(
110  $DIC->http(),
111  $DIC->refinery()
112  );
113 
114  $this->selected_action = $this->user_request->getSelectedAction();
115  $this->user_settings_config = new ilUserSettingsConfig();
116 
117  $this->log = ilLoggerFactory::getLogger('user');
118  $this->requested_ids = $this->user_request->getIds();
119  }
120 
121  private function getTranslationForField(
122  string $field_name,
123  array $properties
124  ): string {
125  $translation = (!isset($properties['lang_var']) || $properties['lang_var'] === '')
126  ? $field_name
127  : $properties['lang_var'];
128 
129  if ($field_name === 'country') {
130  $translation = 'country_free_text';
131  }
132  if ($field_name === 'sel_country') {
133  $translation = 'country_selection';
134  }
135 
136  return $this->lng->txt($translation);
137  }
138 
139  public function setUserOwnerId(int $a_id): void
140  {
141  $this->user_owner_id = $a_id;
142  }
143 
144  public function getUserOwnerId(): int
145  {
146  return $this->user_owner_id ?: USER_FOLDER_ID;
147  }
148 
149  public function executeCommand(): void
150  {
151  $next_class = $this->ctrl->getNextClass($this);
152  $cmd = $this->ctrl->getCmd();
153  $this->prepareOutput();
154 
155  switch ($next_class) {
156  case 'ilusertablegui':
157  $u_table = new ilUserTableGUI(
158  $this,
159  'view'
160  );
161  $u_table->initFilter();
162  $this->ctrl->setReturn(
163  $this,
164  'view'
165  );
166  $this->ctrl->forwardCommand($u_table);
167  break;
168 
169  case 'ilpermissiongui':
170  $perm_gui = new ilPermissionGUI($this);
171  $this->ctrl->forwardCommand($perm_gui);
172  break;
173 
174  case 'ilrepositorysearchgui':
175  if (!$this->access->checkRbacOrPositionPermissionAccess(
176  'read',
179  )) {
180  $this->ilias->raiseError(
181  $this->lng->txt('permission_denied'),
182  $this->ilias->error_obj->MESSAGE
183  );
184  }
185 
186  $user_search = new ilRepositorySearchGUI();
187  $user_search->setTitle($this->lng->txt('search_user_extended')); // #17502
188  $user_search->enableSearchableCheck(false);
189  $user_search->setUserLimitations(false);
190  $user_search->setCallback(
191  $this,
192  'searchResultHandler',
193  $this->getUserMultiCommands(true)
194  );
195  $user_search->addUserAccessFilterCallable([$this, 'searchUserAccessFilterCallable']);
196  $this->tabs_gui->setTabActive('search_user_extended');
197  $this->ctrl->setReturn(
198  $this,
199  'view'
200  );
201  $this->ctrl->forwardCommand($user_search);
202  break;
203 
204  case 'ilcustomuserfieldsgui':
205  $this->raiseErrorOnMissingWrite();
206  $this->tabs_gui->setTabActive('settings');
207  $this->setSubTabs('settings');
208  $this->tabs_gui->activateSubTab('user_defined_fields');
209  $cf = new ilCustomUserFieldsGUI(
210  $this->requested_ref_id,
211  $this->user_request->getFieldId()
212  );
213  $this->ctrl->forwardCommand($cf);
214  break;
215 
216  case 'iluserstartingpointgui':
217  $this->raiseErrorOnMissingWrite();
218  $this->tabs_gui->setTabActive('settings');
219  $this->setSubTabs('settings');
220  $this->tabs_gui->activateSubTab('starting_points');
221  $cf = new ilUserStartingPointGUI($this->ref_id);
222  $this->ctrl->forwardCommand($cf);
223  break;
224 
225  case strtolower(SettingsGUI::class):
226  $this->raiseErrorOnMissingWrite();
227  $this->tabs_gui->setTabActive('settings');
228  $this->setSubTabs('settings');
229  $this->tabs_gui->activateSubTab('user_profile_info');
230  $this->ctrl->forwardCommand(
231  new SettingsGUI(
232  $this->ctrl,
233  $this->lng,
234  $this->ui_factory,
235  $this->ui_renderer,
236  $this->tpl,
237  $this->request,
238  $this->refinery,
239  new PromptRepository(
240  $this->db,
241  $this->lng,
242  new ilSetting('user')
243  )
244  )
245  );
246  break;
247 
248  default:
249  if (!$cmd) {
250  $cmd = 'view';
251  }
252  $cmd .= 'Object';
253  $this->$cmd();
254  break;
255  }
256  }
257 
258  public function resetFilterObject(): void
259  {
260  $utab = new ilUserTableGUI(
261  $this,
262  'view'
263  );
264  $utab->resetOffset();
265  $utab->resetFilter();
266  $this->viewObject();
267  }
268 
272  public function addUserObject(): void
273  {
274  $this->ctrl->setParameterByClass(
275  'ilobjusergui',
276  'new_type',
277  'usr'
278  );
279  $this->ctrl->redirectByClass(
280  ['iladministrationgui', 'ilobjusergui'],
281  'create'
282  );
283  }
284 
285  public function applyFilterObject(): void
286  {
287  $utab = new ilUserTableGUI(
288  $this,
289  'view'
290  );
291  $utab->resetOffset();
292  $utab->writeFilterToSession();
293  $this->viewObject();
294  $this->tabs_gui->activateTab('usrf');
295  }
296 
300  public function viewObject(
301  ): void {
302  if ($this->rbac_system->checkAccess('create_usr', $this->object->getRefId())
303  || $this->rbac_system->checkAccess('cat_administrate_users', $this->object->getRefId())) {
304  $this->toolbar->addComponent(
305  $this->ui_factory->link()->standard(
306  $this->lng->txt('usr_add'),
307  $this->ctrl->getLinkTarget($this, 'addUser')
308  )
309  );
310 
311  $this->toolbar->addComponent(
312  $this->ui_factory->link()->standard(
313  $this->lng->txt('import_users'),
314  $this->ctrl->getLinkTarget($this, 'importUserForm')
315  )
316  );
317  }
318 
319  $list_of_users = null;
320  if (!$this->access->checkAccess('read_users', '', USER_FOLDER_ID)
321  && $this->access->checkRbacOrPositionPermissionAccess(
322  'read_users',
325  )) {
326  $list_of_users = $this->access->filterUserIdsByRbacOrPositionOfCurrentUser(
327  'read_users',
331  );
332  }
333 
334  $utab = new ilUserTableGUI(
335  $this,
336  'view',
338  false
339  );
340  $utab->addFilterItemValue(
341  'user_ids',
342  $list_of_users
343  );
344  $utab->getItems();
345 
346  $this->tpl->setContent($utab->getHTML());
347  }
348 
349  protected function addUserAutoCompleteObject(): void
350  {
351  $auto = new ilUserAutoComplete();
352  $auto->addUserAccessFilterCallable(\Closure::fromCallable([$this, 'filterUserIdsByRbacOrPositionOfCurrentUser']));
353  $auto->setSearchFields(['login', 'firstname', 'lastname', 'email', 'second_email']);
354  $auto->enableFieldSearchableCheck(false);
355  $auto->setMoreLinkAvailable(true);
356 
357  if ($this->user_request->getFetchAll()) {
358  $auto->setLimit(ilUserAutoComplete::MAX_ENTRIES);
359  }
360 
361  echo $auto->getList($this->user_request->getTerm());
362  exit();
363  }
364 
368  public function filterUserIdsByRbacOrPositionOfCurrentUser(array $user_ids): array
369  {
370  return $this->access->filterUserIdsByRbacOrPositionOfCurrentUser(
371  'read_users',
374  $user_ids
375  );
376  }
377 
378  public function chooseLetterObject(): void
379  {
380  $this->ctrl->redirect(
381  $this,
382  'view'
383  );
384  }
385 
390  protected function showPossibleSubObjects(): void
391  {
392  $subobj = null;
393 
394  $d = $this->obj_definition->getCreatableSubObjects($this->object->getType());
395 
396  if (!$this->rbac_system->checkAccess(
397  'create_usr',
398  $this->object->getRefId()
399  )) {
400  unset($d['usr']);
401  }
402 
403  if (count($d) > 0) {
404  foreach ($d as $row) {
405  $count = 0;
406  if ($row['max'] > 0) {
407  //how many elements are present?
408  for ($i = 0, $iMax = count($this->data['ctrl']); $i < $iMax; $i++) {
409  if ($this->data['ctrl'][$i]['type'] == $row['name']) {
410  $count++;
411  }
412  }
413  }
414  if ($row['max'] == '' || $count < $row['max']) {
415  $subobj[] = $row['name'];
416  }
417  }
418  }
419 
420  if (is_array($subobj)) {
421  //build form
423  12,
424  'new_type',
425  $subobj
426  );
427  $this->tpl->setCurrentBlock('add_object');
428  $this->tpl->setVariable(
429  'SELECT_OBJTYPE',
430  $opts
431  );
432  $this->tpl->setVariable(
433  'BTN_NAME',
434  'create'
435  );
436  $this->tpl->setVariable(
437  'TXT_ADD',
438  $this->lng->txt('add')
439  );
440  $this->tpl->parseCurrentBlock();
441  }
442  }
443 
444  public function cancelUserFolderActionObject(): void
445  {
446  $this->ctrl->redirect(
447  $this,
448  'view'
449  );
450  }
451 
452  public function cancelSearchActionObject(): void
453  {
454  $this->ctrl->redirectByClass(
455  'ilrepositorysearchgui',
456  'showSearchResults'
457  );
458  }
459 
460  public function confirmactivateObject(): void
461  {
462  if (!$this->checkUserManipulationAccessBool()) {
463  $this->ilias->raiseError(
464  $this->lng->txt('msg_no_perm_write'),
465  $this->ilias->error_obj->WARNING
466  );
467  }
468 
469  // FOR ALL SELECTED OBJECTS
470  foreach ($this->getActionUserIds() as $id) {
472  $id,
473  false
474  );
475  if ($obj instanceof \ilObjUser) {
476  if (!$obj->getActive()) {
477  $obj->setLoginAttempts(0);
478  }
479  $obj->setActive(
480  true,
481  $this->user->getId()
482  );
483  $obj->update();
484  }
485  }
486 
487  $this->tpl->setOnScreenMessage('success', $this->lng->txt('user_activated'), true);
488 
489  if ($this->user_request->getFrSearch()) {
490  $this->ctrl->redirectByClass(
491  'ilRepositorySearchGUI',
492  'show'
493  );
494  } else {
495  $this->ctrl->redirect(
496  $this,
497  'view'
498  );
499  }
500  }
501 
502  public function confirmdeactivateObject(): void
503  {
504  if (!$this->checkUserManipulationAccessBool()) {
505  $this->ilias->raiseError(
506  $this->lng->txt('msg_no_perm_write'),
507  $this->ilias->error_obj->WARNING
508  );
509  }
510  // FOR ALL SELECTED OBJECTS
511  foreach ($this->getActionUserIds() as $id) {
513  $id,
514  false
515  );
516  if ($obj instanceof \ilObjUser) {
517  $obj->setActive(
518  false,
519  $this->user->getId()
520  );
521  $obj->update();
522  }
523  }
524 
525  // Feedback
526  $this->tpl->setOnScreenMessage('success', $this->lng->txt('user_deactivated'), true);
527 
528  if ($this->user_request->getFrSearch()) {
529  $this->ctrl->redirectByClass(
530  'ilRepositorySearchGUI',
531  'show'
532  );
533  } else {
534  $this->ctrl->redirect(
535  $this,
536  'view'
537  );
538  }
539  }
540 
541  protected function confirmaccessFreeObject(): void
542  {
543  if (!$this->checkUserManipulationAccessBool()) {
544  $this->ilias->raiseError(
545  $this->lng->txt('msg_no_perm_write'),
546  $this->ilias->error_obj->WARNING
547  );
548  }
549 
550  foreach ($this->getActionUserIds() as $id) {
552  $id,
553  false
554  );
555  if ($obj instanceof \ilObjUser) {
556  $obj->setTimeLimitUnlimited(true);
557  $obj->setTimeLimitFrom(null);
558  $obj->setTimeLimitUntil(null);
559  $obj->setTimeLimitMessage('');
560  $obj->update();
561  }
562  }
563 
564  // Feedback
565  $this->tpl->setOnScreenMessage('success', $this->lng->txt('access_free_granted'), true);
566 
567  if ($this->user_request->getFrSearch()) {
568  $this->ctrl->redirectByClass(
569  'ilRepositorySearchGUI',
570  'show'
571  );
572  } else {
573  $this->ctrl->redirect(
574  $this,
575  'view'
576  );
577  }
578  }
579 
580  public function setAccessRestrictionObject(
581  ?ilPropertyFormGUI $a_form = null,
582  bool $a_from_search = false
583  ): bool {
584  if (!$a_form) {
585  $a_form = $this->initAccessRestrictionForm($a_from_search);
586  }
587  $this->tpl->setContent($a_form->getHTML());
588 
589  // #10963
590  return true;
591  }
592 
593  protected function initAccessRestrictionForm(
594  bool $a_from_search = false
595  ): ?ilPropertyFormGUI {
596  $user_ids = $this->getActionUserIds();
597  if (!$user_ids) {
598  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
599  $this->viewObject();
600  return null;
601  }
602 
603  $form = new ilPropertyFormGUI();
604  $form->setTitle($this->lng->txt('time_limit_add_time_limit_for_selected'));
605  $form->setFormAction(
606  $this->ctrl->getFormAction(
607  $this,
608  'confirmaccessRestrict'
609  )
610  );
611 
612  $from = new ilDateTimeInputGUI(
613  $this->lng->txt('access_from'),
614  'from'
615  );
616  $from->setShowTime(true);
617  $from->setRequired(true);
618  $form->addItem($from);
619 
620  $to = new ilDateTimeInputGUI(
621  $this->lng->txt('access_until'),
622  'to'
623  );
624  $to->setRequired(true);
625  $to->setShowTime(true);
626  $form->addItem($to);
627 
628  $form->addCommandButton(
629  'confirmaccessRestrict',
630  $this->lng->txt('confirm')
631  );
632  $form->addCommandButton(
633  'view',
634  $this->lng->txt('cancel')
635  );
636 
637  foreach ($user_ids as $user_id) {
638  $ufield = new ilHiddenInputGUI('id[]');
639  $ufield->setValue((string) $user_id);
640  $form->addItem($ufield);
641  }
642 
643  // return to search?
644  if ($a_from_search || $this->user_request->getFrSearch()) {
645  $field = new ilHiddenInputGUI('frsrch');
646  $field->setValue('1');
647  $form->addItem($field);
648  }
649 
650  return $form;
651  }
652 
658  protected function confirmaccessRestrictObject(): bool
659  {
660  $form = $this->initAccessRestrictionForm();
661  if (!$form->checkInput()) {
662  return $this->setAccessRestrictionObject($form);
663  }
664 
665  $timefrom = $form->getItemByPostVar('from')->getDate()->get(IL_CAL_UNIX);
666  $timeuntil = $form->getItemByPostVar('to')->getDate()->get(IL_CAL_UNIX);
667  if ($timeuntil <= $timefrom) {
668  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('time_limit_not_valid'));
669  return $this->setAccessRestrictionObject($form);
670  }
671 
672  if (!$this->checkUserManipulationAccessBool()) {
673  $this->ilias->raiseError(
674  $this->lng->txt('msg_no_perm_write'),
675  $this->ilias->error_obj->WARNING
676  );
677  }
678  foreach ($this->getActionUserIds() as $id) {
680  $id,
681  false
682  );
683  if ($obj instanceof \ilObjUser) {
684  $obj->setTimeLimitUnlimited(false);
685  $obj->setTimeLimitFrom((int) $timefrom);
686  $obj->setTimeLimitUntil((int) $timeuntil);
687  $obj->setTimeLimitMessage('');
688  $obj->update();
689  }
690  }
691  $this->tpl->setOnScreenMessage('success', $this->lng->txt('access_restricted'), true);
692 
693  if ($this->user_request->getFrSearch()) {
694  $this->ctrl->redirectByClass(
695  'ilRepositorySearchGUI',
696  'show'
697  );
698  } else {
699  $this->ctrl->redirect(
700  $this,
701  'view'
702  );
703  }
704  return false;
705  }
706 
707  public function confirmdeleteObject(): void
708  {
709  if (!$this->rbac_system->checkAccess(
710  'delete',
711  $this->object->getRefId()
712  )) {
713  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_perm_delete'), true);
714  $this->ctrl->redirect(
715  $this,
716  'view'
717  );
718  }
719 
720  $ids = $this->user_request->getIds();
721  if (in_array(
722  $this->user->getId(),
723  $ids
724  )) {
725  $this->ilias->raiseError(
726  $this->lng->txt('msg_no_delete_yourself'),
727  $this->ilias->error_obj->WARNING
728  );
729  }
730 
731  // FOR ALL SELECTED OBJECTS
732  foreach ($ids as $id) {
733  // instatiate correct object class (usr)
735  $obj->delete();
736  }
737 
738  // Feedback
739  $this->tpl->setOnScreenMessage('success', $this->lng->txt('user_deleted'), true);
740 
741  if ($this->user_request->getFrSearch()) {
742  $this->ctrl->redirectByClass(
743  'ilRepositorySearchGUI',
744  'show'
745  );
746  } else {
747  $this->ctrl->redirect(
748  $this,
749  'view'
750  );
751  }
752  }
753 
758  protected function getActionUserIds(): array
759  {
760  if ($this->getSelectAllPostArray()['select_cmd_all']) {
761  $utab = new ilUserTableGUI(
762  $this,
763  'view',
765  false
766  );
767 
768  if (!$this->access->checkAccess(
769  'read_users',
770  '',
772  ) &&
773  $this->access->checkRbacOrPositionPermissionAccess(
774  'read_users',
777  )) {
779  $filtered_users = $this->access->filterUserIdsByRbacOrPositionOfCurrentUser(
780  'read_users',
783  $users
784  );
785 
786  $utab->addFilterItemValue(
787  'user_ids',
788  $filtered_users
789  );
790  }
791 
792  return $utab->getUserIdsForFilter();
793  } else {
794  return $this->access->filterUserIdsByRbacOrPositionOfCurrentUser(
795  'read_users',
798  $this->requested_ids
799  );
800  }
801  }
802 
803  private function checkUserManipulationAccessBool(): bool
804  {
805  return $this->access->checkRbacOrPositionPermissionAccess(
806  'write',
809  );
810  }
811 
812  public function showActionConfirmation(
813  string $action,
814  bool $a_from_search = false
815  ): bool {
816  $user_ids = $this->getActionUserIds();
817  if (!$user_ids) {
818  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('no_checkbox'));
819  $this->viewObject();
820  return false;
821  }
822 
823  if (!$a_from_search) {
824  $this->tabs_gui->activateTab('obj_usrf');
825  } else {
826  $this->tabs_gui->activateTab('search_user_extended');
827  }
828 
829  if (strcmp(
830  $action,
831  'accessRestrict'
832  ) == 0) {
833  return $this->setAccessRestrictionObject(
834  null,
835  $a_from_search
836  );
837  }
838  if (strcmp(
839  $action,
840  'mail'
841  ) == 0) {
842  $this->mailObject();
843  return false;
844  }
845  if (strcmp($action, 'addToClipboard') === 0) {
846  $this->addToClipboardObject();
847  return false;
848  }
849 
850  unset($this->data);
851 
852  if (!$a_from_search) {
853  $cancel = 'cancelUserFolderAction';
854  } else {
855  $cancel = 'cancelSearchAction';
856  }
857 
858  // display confirmation message
859  $cgui = new ilConfirmationGUI();
860  $cgui->setFormAction($this->ctrl->getFormAction($this));
861  $cgui->setHeaderText($this->lng->txt('info_' . $action . '_sure'));
862  $cgui->setCancel(
863  $this->lng->txt('cancel'),
864  $cancel
865  );
866  $cgui->setConfirm(
867  $this->lng->txt('confirm'),
868  'confirm' . $action
869  );
870 
871  if ($a_from_search) {
872  $cgui->addHiddenItem(
873  'frsrch',
874  '1'
875  );
876  }
877 
878  foreach ($user_ids as $id) {
879  $user = new ilObjUser((int) $id);
880 
881  $login = $user->getLastLogin();
882  if (!$login) {
883  $login = $this->lng->txt('never');
884  } else {
886  new ilDateTime(
887  $login,
889  )
890  );
891  }
892 
893  $caption = $user->getFullname() . ' (' . $user->getLogin() . ')' . ', ' .
894  $user->getEmail() . ' - ' . $this->lng->txt('last_login') . ': ' . $login;
895 
896  $cgui->addItem(
897  'id[]',
898  (string) $id,
899  $caption
900  );
901  }
902 
903  $this->tpl->setContent($cgui->getHTML());
904 
905  return true;
906  }
907 
908  public function deleteUsersObject(): void
909  {
910  if (!$this->access->checkRbacOrPositionPermissionAccess(
911  'delete',
914  )) {
915  $this->ilias->raiseError(
916  $this->lng->txt('permission_denied'),
917  $this->ilias->error_obj->MESSAGE
918  );
919  }
920 
921  if (in_array($this->user->getId(), $this->getActionUserIds())) {
922  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_delete_yourself'));
923  $this->viewObject();
924  return;
925  }
926  $this->showActionConfirmation('delete');
927  }
928 
929  public function activateUsersObject(): void
930  {
931  $this->raiseErrorOnMissingWrite();
932  $this->showActionConfirmation('activate');
933  }
934 
935  public function deactivateUsersObject(): void
936  {
937  $this->raiseErrorOnMissingWrite();
938  if (in_array($this->user->getId(), $this->getActionUserIds())) {
939  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('no_deactivate_yourself'));
940  $this->viewObject();
941  return;
942  }
943  $this->showActionConfirmation('deactivate');
944  }
945 
946  public function restrictAccessObject(): void
947  {
948  $this->raiseErrorOnMissingWrite();
949  $this->showActionConfirmation('accessRestrict');
950  }
951 
952  public function freeAccessObject(): void
953  {
954  $this->raiseErrorOnMissingWrite();
955  $this->showActionConfirmation('accessFree');
956  }
957 
958  public function userActionObject(): void
959  {
960  $this->raiseErrorOnMissingWrite();
961  $this->showActionConfirmation($this->user_request->getSelectedAction());
962  }
963 
964  public function importUserFormObject(): void
965  {
966  $this->tabs_gui->clearTargets();
967  $this->tabs_gui->setBackTarget(
968  $this->lng->txt('usrf'),
969  $this->ctrl->getLinkTarget(
970  $this,
971  'view'
972  )
973  );
974  if (
975  !$this->rbac_system->checkAccess('create_usr', $this->object->getRefId())
976  && !$this->access->checkAccess('cat_administrate_users', '', $this->object->getRefId())
977  ) {
978  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'));
979  return;
980  }
981  $this->initUserImportForm();
982  $this->tpl->setContent($this->form->getHTML());
983  }
984 
985  public function initUserImportForm(): void
986  {
987  $this->form = new ilPropertyFormGUI();
988 
989  // Import File
990  $fi = new ilFileInputGUI(
991  $this->lng->txt('import_file'),
992  'importFile'
993  );
994  $fi->setSuffixes(['xml']);
995  $fi->setRequired(true);
996  $this->form->addItem($fi);
997 
998  $this->form->addCommandButton(
999  'importUserRoleAssignment',
1000  $this->lng->txt('import')
1001  );
1002  $this->form->addCommandButton(
1003  'importCancelled',
1004  $this->lng->txt('cancel')
1005  );
1006 
1007  $this->form->setTitle($this->lng->txt('import_users'));
1008  $this->form->setFormAction($this->ctrl->getFormAction($this));
1009  }
1010 
1011  protected function inAdministration(): bool
1012  {
1013  return (strtolower($this->user_request->getBaseClass()) === 'iladministrationgui');
1014  }
1015 
1016  public function importCancelledObject(): void
1017  {
1018  $import_dir = $this->getImportDir();
1019  if ($this->filesystem->hasDir($import_dir)) {
1020  $this->filesystem->deleteDir($import_dir);
1021  }
1022 
1023  if ($this->inAdministration()) {
1024  $this->ctrl->redirect(
1025  $this,
1026  'view'
1027  );
1028  } else {
1029  $this->ctrl->redirectByClass(
1030  'ilobjcategorygui',
1031  'listUsers'
1032  );
1033  }
1034  }
1035 
1036  public function getImportDir(): string
1037  {
1038  // For each user session a different directory must be used to prevent
1039  // that one user session overwrites the import data that another session
1040  // is currently importing.
1041 
1042  $importDir = 'user_import/usr_' . $this->user->getId() . '_' . mb_substr(session_id(), 0, 8);
1043 
1044  return $importDir;
1045  }
1046 
1050  public function importUserRoleAssignmentObject(): void
1051  {
1052  $this->tabs_gui->clearTargets();
1053  $this->tabs_gui->setBackTarget(
1054  $this->lng->txt('usrf'),
1055  $this->ctrl->getLinkTarget(
1056  $this,
1057  'view'
1058  )
1059  );
1060 
1061  $this->initUserImportForm();
1062  if ($this->form->checkInput()) {
1063  $xml_file = $this->handleUploadedFiles();
1064  $xml_file_full_path = ilFileUtils::getDataDir() . '/' . $xml_file;
1065 
1066  list($form, $message) = $this->initUserRoleAssignmentForm($xml_file_full_path);
1067 
1068  $this->tpl->setContent($message . $this->ui_renderer->render($form));
1069  } else {
1070  $this->form->setValuesByPost();
1071  $this->tpl->setContent($this->form->getHTML());
1072  }
1073  }
1074 
1079  private function initUserRoleAssignmentForm(string $xml_file_full_path): array
1080  {
1081  $global_roles_assignment_info = null;
1082  $local_roles_assignment_info = null;
1083 
1084  $import_parser = new ilUserImportParser(
1085  $xml_file_full_path,
1087  );
1088  $import_parser->startParsing();
1089 
1090  $message = $this->verifyXmlData($import_parser);
1091 
1092  $xml_file_name = explode(
1093  '/',
1094  $xml_file_full_path
1095  );
1096  $roles_import_filename = $this->ui_factory->input()->field()
1097  ->text($this->lng->txt('import_file'))
1098  ->withDisabled(true)
1099  ->withValue(end($xml_file_name));
1100 
1101  $roles_import_count = $this->ui_factory->input()->field()
1102  ->numeric($this->lng->txt('num_users'))
1103  ->withDisabled(true)
1104  ->withValue($import_parser->getUserCount());
1105 
1106  $import_parser = new ilUserImportParser(
1107  $xml_file_full_path,
1109  );
1110  $import_parser->startParsing();
1111 
1112  $roles = $import_parser->getCollectedRoles();
1113  $all_gl_roles = $this->rbac_review->getRoleListByObject(ROLE_FOLDER_ID);
1114  $gl_roles = [];
1115  $roles_of_user = $this->rbac_review->assignedRoles($this->user->getId());
1116  foreach ($all_gl_roles as $obj_data) {
1117  // check assignment permission if called from local admin
1118  if ($this->object->getRefId() != USER_FOLDER_ID
1119  && !in_array(SYSTEM_ROLE_ID, $roles_of_user)
1120  && !ilObjRole::_getAssignUsersStatus($obj_data['obj_id'])
1121  ) {
1122  continue;
1123  }
1124  // exclude anonymous role from list
1125  if ($obj_data['obj_id'] != ANONYMOUS_ROLE_ID
1126  && ($obj_data['obj_id'] != SYSTEM_ROLE_ID
1127  || in_array(SYSTEM_ROLE_ID, $roles_of_user))
1128  ) {
1129  $gl_roles[$obj_data['obj_id']] = $obj_data['title'];
1130  }
1131  }
1132 
1133  // global roles
1134  $got_globals = false;
1135  $global_selects = [];
1136  foreach ($roles as $role_id => $role) {
1137  if ($role['type'] === 'Global') {
1138  $select_options = [];
1139  if (!$got_globals) {
1140  $global_roles_assignment_info = $this->ui_factory->input()->field()
1141  ->text($this->lng->txt('roles_of_import_global'))
1142  ->withDisabled(true)
1143  ->withValue($this->lng->txt('assign_global_role'));
1144  } else {
1145  $select_options[] = $this->lng->txt('usrimport_ignore_role');
1146  }
1147 
1148  foreach ($gl_roles as $key => $value) {
1149  $select_options[$role_id . '-' . $key] = $value;
1150  }
1151 
1152  // pre selection for role
1153  $pre_select = array_search(
1154  $role['name'],
1155  $select_options
1156  );
1157  if (!$pre_select) {
1158  switch ($role['name']) {
1159  case 'Administrator': // ILIAS 2/3 Administrator
1160  $pre_select = array_search(
1161  'Administrator',
1162  $select_options
1163  );
1164  break;
1165 
1166  case 'Autor': // ILIAS 2 Author
1167  $pre_select = array_search(
1168  'User',
1169  $select_options
1170  );
1171  break;
1172 
1173  case 'Lerner': // ILIAS 2 Learner
1174  $pre_select = array_search(
1175  'User',
1176  $select_options
1177  );
1178  break;
1179 
1180  case 'Gast': // ILIAS 2 Guest
1181  $pre_select = array_search(
1182  'Guest',
1183  $select_options
1184  );
1185  break;
1186 
1187  case 'User':
1188  $pre_select = array_search(
1189  'User',
1190  $select_options
1191  );
1192  break;
1193  }
1194  }
1195 
1196  $select = $this->ui_factory->input()->field()
1197  ->select(
1198  $role['name'],
1199  $select_options
1200  )
1201  ->withValue($pre_select);
1202 
1203  if (!$got_globals) {
1204  $got_globals = true;
1205  $global_selects[] = $select->withRequired(true);
1206  } else {
1207  $global_selects[] = $select;
1208  }
1209  }
1210  }
1211 
1212  // Check if local roles need to be assigned
1213  $got_locals = false;
1214  foreach ($roles as $role_id => $role) {
1215  if ($role['type'] == 'Local') {
1216  $got_locals = true;
1217  break;
1218  }
1219  }
1220 
1221  if ($got_locals) {
1222  $local_roles_assignment_info = $this->ui_factory->input()->field()
1223  ->text($this->lng->txt('roles_of_import_local'))
1224  ->withDisabled(true)
1225  ->withValue($this->lng->txt('assign_local_role'));
1226 
1227  // get local roles
1228  if ($this->object->getRefId() == USER_FOLDER_ID) {
1229  // The import function has been invoked from the user folder
1230  // object. In this case, we show only matching roles,
1231  // because the user folder object is considered the parent of all
1232  // local roles and may contains thousands of roles on large ILIAS
1233  // installations.
1234  $loc_roles = [];
1235 
1236  $roleMailboxSearch = new ilRoleMailboxSearch(new ilMailRfc822AddressParserFactory());
1237  foreach ($roles as $role_id => $role) {
1238  if ($role['type'] == 'Local') {
1239  $searchName = (strpos($role['name'], '#') === 0) ? $role['name'] : '#' . $role['name'];
1240  $matching_role_ids = $roleMailboxSearch->searchRoleIdsByAddressString($searchName);
1241  foreach ($matching_role_ids as $mid) {
1242  if (!in_array(
1243  $mid,
1244  $loc_roles
1245  )) {
1246  $loc_roles[] = $mid;
1247  }
1248  }
1249  }
1250  }
1251  } else {
1252  // The import function has been invoked from a locally
1253  // administrated category. In this case, we show all roles
1254  // contained in the subtree of the category.
1255  $loc_roles = $this->rbac_review->getAssignableRolesInSubtree($this->object->getRefId());
1256  }
1257  $l_roles = [];
1258 
1259  // create a search array with .
1260  foreach ($loc_roles as $key => $loc_role) {
1261  // fetch context path of role
1262  $rolf = $this->rbac_review->getFoldersAssignedToRole(
1263  $loc_role,
1264  true
1265  );
1266 
1267  // only process role folders that are not set to status 'deleted'
1268  // and for which the user has write permissions.
1269  // We also don't show the roles which are in the ROLE_FOLDER_ID folder.
1270  // (The ROLE_FOLDER_ID folder contains the global roles).
1271  if (
1272  !$this->rbac_review->isDeleted($rolf[0]) &&
1273  $this->rbac_system->checkAccess(
1274  'write',
1275  $rolf[0]
1276  ) &&
1277  $rolf[0] != ROLE_FOLDER_ID
1278  ) {
1279  // A local role is only displayed, if it is contained in the subtree of
1280  // the localy administrated category. If the import function has been
1281  // invoked from the user folder object, we show all local roles, because
1282  // the user folder object is considered the parent of all local roles.
1283  // Thus, if we start from the user folder object, we initialize the
1284  // isInSubtree variable with true. In all other cases it is initialized
1285  // with false, and only set to true if we find the object id of the
1286  // locally administrated category in the tree path to the local role.
1287  $is_in_subtree = $this->object->getRefId() == USER_FOLDER_ID;
1288 
1289  $path_array = [];
1290  if ($this->tree->isInTree($rolf[0])) {
1291  // Create path. Paths which have more than 4 segments
1292  // are truncated in the middle.
1293  $tmpPath = $this->tree->getPathFull($rolf[0]);
1294  $tmpPath[] = $rolf[0];//adds target item to list
1295 
1296  for ($i = 1, $n = count($tmpPath) - 1; $i < $n; $i++) {
1297  if ($i < 3 || $i > $n - 3) {
1298  $path_array[] = $tmpPath[$i]['title'];
1299  } elseif ($i == 3 || $i == $n - 3) {
1300  $path_array[] = '...';
1301  }
1302 
1303  $is_in_subtree |= $tmpPath[$i]['obj_id'] == $this->object->getId();
1304  }
1305  //revert this path for a better readability in dropdowns #18306
1306  $path = implode(
1307  ' < ',
1308  array_reverse($path_array)
1309  );
1310  } else {
1311  $path = '<b>Rolefolder ' . $rolf[0] . ' not found in tree! (Role ' . $loc_role . ')</b>';
1312  }
1313  $roleMailboxAddress = (new \ilRoleMailboxAddress($loc_role))->value();
1314  $l_roles[$loc_role] = $roleMailboxAddress . ', ' . $path;
1315  }
1316  }
1317 
1318  natcasesort($l_roles);
1319  $l_roles['ignore'] = $this->lng->txt('usrimport_ignore_role');
1320 
1321  $roleMailboxSearch = new ilRoleMailboxSearch(new ilMailRfc822AddressParserFactory());
1322  $local_selects = [];
1323  foreach ($roles as $role_id => $role) {
1324  if ($role['type'] == 'Local') {
1325  $searchName = (strpos($role['name'], '#') === 0) ? $role['name'] : '#' . $role['name'];
1326  $matching_role_ids = $roleMailboxSearch->searchRoleIdsByAddressString($searchName);
1327  $pre_select = count($matching_role_ids) == 1 ? $role_id . '-' . $matching_role_ids[0] : 'ignore';
1328 
1329  $selectable_roles = [];
1330  if ($this->object->getRefId() == USER_FOLDER_ID) {
1331  // There are too many roles in a large ILIAS installation
1332  // that's why whe show only a choice with the the option 'ignore',
1333  // and the matching roles.
1334  $selectable_roles['ignore'] = $this->lng->txt('usrimport_ignore_role');
1335  foreach ($matching_role_ids as $id) {
1336  $selectable_roles[$role_id . '-' . $id] = $l_roles[$id];
1337  }
1338  } else {
1339  foreach ($l_roles as $local_role_id => $value) {
1340  if ($local_role_id !== 'ignore') {
1341  $selectable_roles[$role_id . '-' . $local_role_id] = $value;
1342  }
1343  }
1344  }
1345 
1346  if (count($selectable_roles) > 0) {
1347  $select = $this->ui_factory->input()->field()
1348  ->select($role['name'], $selectable_roles)
1349  ->withRequired(true);
1350  if (array_key_exists($pre_select, $selectable_roles)) {
1351  $select = $select->withValue($pre_select);
1352  }
1353  $local_selects[] = $select;
1354  }
1355  }
1356  }
1357  }
1358 
1359  $handlers = [
1360  ilUserImportParser::IL_IGNORE_ON_CONFLICT => $this->lng->txt('ignore_on_conflict'),
1361  ilUserImportParser::IL_UPDATE_ON_CONFLICT => $this->lng->txt('update_on_conflict')
1362  ];
1363 
1364  $conflict_action_select = $this->ui_factory->input()->field()
1365  ->select(
1366  $this->lng->txt('conflict_handling'),
1367  $handlers,
1368  str_replace(
1369  '\n',
1370  '<br>',
1371  $this->lng->txt('usrimport_conflict_handling_info')
1372  )
1373  )
1375  ->withRequired(true);
1376 
1377  // new account mail
1378  $this->lng->loadLanguageModule('mail');
1379  $amail = ilObjUserFolder::_lookupNewAccountMail($this->lng->getDefaultLanguage());
1380  $mail_section = null;
1381  if (trim($amail['body'] ?? '') != '' && trim($amail['subject'] ?? '') != '') {
1382  $send_checkbox = $this->ui_factory->input()->field()->checkbox($this->lng->txt('user_send_new_account_mail'))
1383  ->withValue(true);
1384 
1385  $mail_section = $this->ui_factory->input()->field()->section(
1386  [$send_checkbox],
1387  $this->lng->txt('mail_account_mail')
1388  );
1389  }
1390 
1391  $file_info_section = $this->ui_factory->input()->field()->section(
1392  [
1393  'filename' => $roles_import_filename,
1394  'import_count' => $roles_import_count,
1395  ],
1396  $this->lng->txt('file_info')
1397  );
1398 
1399  $form_action = $this->ctrl->getFormActionByClass(self::class, 'importUsers');
1400 
1401  $form_elements = [
1402  'file_info' => $file_info_section
1403  ];
1404 
1405  if (!empty($global_selects)) {
1406  $global_role_info_section = $this->ui_factory->input()
1407  ->field()
1408  ->section([$global_roles_assignment_info], $this->lng->txt('global_role_assignment'));
1409  $global_role_selection_section = $this->ui_factory->input()->field()->section($global_selects, '');
1410  $form_elements['global_role_info'] = $global_role_info_section;
1411  $form_elements['global_role_selection'] = $global_role_selection_section;
1412  }
1413 
1414  if (!empty($local_selects)) {
1415  $local_role_info_section = $this->ui_factory->input()->field()->section(
1416  [$local_roles_assignment_info],
1417  $this->lng->txt('local_role_assignment')
1418  );
1419  $local_role_selection_section = $this->ui_factory->input()->field()->section(
1420  $local_selects,
1421  ''
1422  );
1423 
1424  $form_elements['local_role_info'] = $local_role_info_section;
1425  $form_elements['local_role_selection'] = $local_role_selection_section;
1426  }
1427 
1428  $form_elements['conflict_action'] = $this->ui_factory->input()->field()->section([$conflict_action_select], '');
1429 
1430  if ($mail_section !== null) {
1431  $form_elements['send_mail'] = $mail_section;
1432  }
1433 
1434  return [$this->ui_factory->input()->container()->form()->standard(
1435  $form_action,
1436  $form_elements
1437  ), $message];
1438  }
1439 
1440  private function handleUploadedFiles(): string
1441  {
1442  $subdir = '';
1443  $xml_file = '';
1444 
1445  $import_dir = $this->getImportDir();
1446 
1447  if (!$this->upload->hasBeenProcessed()) {
1448  $this->upload->process();
1449  }
1450 
1451  // recreate user import directory
1452  if ($this->filesystem->hasDir($import_dir)) {
1453  $this->filesystem->deleteDir($import_dir);
1454  }
1455  $this->filesystem->createDir($import_dir);
1456 
1457  foreach ($this->upload->getResults() as $single_file_upload) {
1458  $file_name = $single_file_upload->getName();
1459  $parts = pathinfo($file_name);
1460 
1461  //check if upload status is ok
1462  if (!$single_file_upload->isOK()) {
1463  $this->filesystem->deleteDir($import_dir);
1464  $this->ilias->raiseError(
1465  $this->lng->txt('no_import_file_found'),
1466  $this->ilias->error_obj->MESSAGE
1467  );
1468  }
1469 
1470  // move uploaded file to user import directory
1471  $this->upload->moveFilesTo(
1472  $import_dir,
1473  \ILIAS\FileUpload\Location::STORAGE
1474  );
1475 
1476  // handle zip file
1477  if ($single_file_upload->getMimeType() == 'application/zip') {
1478  // Workaround: unzip function needs full path to file. Should be replaced once Filesystem has own unzip implementation
1479  $full_path = ilFileUtils::getDataDir() . '/user_import/usr_'
1480  . $this->user->getId() . '_' . session_id() . '/' . $file_name;
1481  $this->dic->legacyArchives()->unzip($full_path);
1482 
1483  $xml_file = null;
1484  $file_list = $this->filesystem->listContents($import_dir);
1485 
1486  foreach ($file_list as $key => $a_file) {
1487  if (substr(
1488  $a_file->getPath(),
1489  -4
1490  ) == '.xml') {
1491  unset($file_list[$key]);
1492  $xml_file = $a_file->getPath();
1493  break;
1494  }
1495  }
1496 
1497  //Removing all files except the one to be imported, to make sure to get the right one in import-function
1498  foreach ($file_list as $a_file) {
1499  $this->filesystem->delete($a_file->getPath());
1500  }
1501 
1502  if (is_null($xml_file)) {
1503  $subdir = basename(
1504  $parts['basename'],
1505  '.' . $parts['extension']
1506  );
1507  $xml_file = $import_dir . '/' . $subdir . '/' . $subdir . '.xml';
1508  }
1509  } // handle xml file
1510  else {
1511  $a = $this->filesystem->listContents($import_dir);
1512  $file = end($a);
1513  $xml_file = $file->getPath();
1514  }
1515 
1516  // check xml file
1517  if (!$this->filesystem->has($xml_file)) {
1518  $this->filesystem->deleteDir($import_dir);
1519  $this->ilias->raiseError(
1520  $this->lng->txt('no_xml_file_found_in_zip')
1521  . ' ' . $subdir . '/' . $subdir . '.xml',
1522  $this->ilias->error_obj->MESSAGE
1523  );
1524  }
1525  }
1526 
1527  return $xml_file;
1528  }
1529 
1530  public function verifyXmlData(ilUserImportParser $import_parser): string
1531  {
1532  $import_dir = $this->getImportDir();
1533  switch ($import_parser->getErrorLevel()) {
1535  return '';
1537  return $import_parser->getProtocolAsHTML($this->lng->txt("verification_warning_log"));
1539  $this->filesystem->deleteDir($import_dir);
1540  $this->tpl->setOnScreenMessage(
1541  'failure',
1542  $this->lng->txt('verification_failed') . $import_parser->getProtocolAsHTML(
1543  $this->lng->txt('verification_failure_log')
1544  ),
1545  true
1546  );
1547  $this->ctrl->redirectByClass(self::class, 'importUserForm');
1548  }
1549  }
1550 
1554  public function importUsersObject(): void
1555  {
1556  $result = [];
1557  $xml_file = '';
1558  $import_dir = $this->getImportDir();
1559 
1560  $file_list = $this->filesystem->listContents($import_dir);
1561 
1562  if (count($file_list) > 1) {
1563  $this->filesystem->deleteDir($import_dir);
1564  $this->tpl->setOnScreenMessage($this->lng->txt('usrimport_wrong_file_count'), true);
1565  $this->redirectAfterImport();
1566  }
1567  $xml_file = $file_list[0]->getPath();
1568 
1569  //Need full path to xml file to initialise form
1570  $xml_path = ilFileUtils::getDataDir() . '/' . $xml_file;
1571 
1572  if (!$this->user_request->isPost()) {
1573  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('usrimport_form_not_evaluabe'), true);
1574  $this->redirectAfterImport();
1575  }
1576 
1577  $form = $this->initUserRoleAssignmentForm($xml_path)[0]->withRequest($this->user_request->getRequest());
1578  $result = $form->getData();
1579 
1580  if ($result === null) {
1581  $this->tpl->setContent($this->ui_renderer->render($form));
1582  return;
1583  }
1584 
1585  $rule = $result['conflict_action'][0] ?? 1;
1586 
1587  //If local roles exist, merge the roles that are to be assigned, otherwise just take the array that has global roles
1588  $local_role_selection = (array) ($result['local_role_selection'] ?? []);
1589  $global_role_selection = (array) ($result['global_role_selection'] ?? []);
1590  $roles = array_merge(
1591  $local_role_selection,
1592  $global_role_selection
1593  );
1594 
1595  $role_assignment = [];
1596  foreach ($roles as $value) {
1597  $keys = explode(
1598  '-',
1599  $value
1600  );
1601  if (count($keys) === 2) {
1602  $role_assignment[$keys[0]] = $keys[1];
1603  }
1604  }
1605 
1606  $import_parser = new ilUserImportParser(
1607  $xml_path,
1609  (int) $rule
1610  );
1611  $import_parser->setFolderId($this->getUserOwnerId());
1612 
1613  // Catch hack attempts
1614  // We check here again, if the role folders are in the tree, and if the
1615  // user has permission on the roles.
1616  if (!empty($role_assignment)) {
1617  $global_roles = $this->rbac_review->getGlobalRoles();
1618  $roles_of_user = $this->rbac_review->assignedRoles($this->user->getId());
1619  foreach ($role_assignment as $role_id_string) {
1620  $role_id = $this->refinery->byTrying([
1621  $this->refinery->kindlyTo()->int(),
1622  $this->refinery->always(null)
1623  ])->transform($role_id_string);
1624  if ($role_id === null) {
1625  continue;
1626  }
1628  $role_id,
1629  $roles_of_user,
1630  $global_roles,
1631  $xml_path
1632  );
1633  }
1634  }
1635 
1636  if (isset($result['send_mail'])) {
1637  $import_parser->setSendMail($result['send_mail'][0]);
1638  }
1639 
1640  $import_parser->setRoleAssignment($role_assignment);
1641  $import_parser->startParsing();
1642 
1643  // purge user import directory
1644  $this->filesystem->deleteDir($import_dir);
1645 
1646  switch ($import_parser->getErrorLevel()) {
1648  $this->tpl->setOnScreenMessage(
1649  'success',
1650  $this->lng->txt('user_imported'),
1651  true
1652  );
1653  break;
1655  $this->tpl->setOnScreenMessage(
1656  'success',
1657  $this->lng->txt('user_imported_with_warnings')
1658  . $import_parser->getProtocolAsHTML(
1659  $this->lng->txt('import_warning_log')
1660  ),
1661  true
1662  );
1663  break;
1665  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('user_import_failed'), true);
1666  $this->redirectAfterImport();
1667  break;
1668  }
1669 
1670  if ($this->inAdministration()) {
1671  $this->ctrl->redirect(
1672  $this,
1673  'view'
1674  );
1675  } else {
1676  $this->ctrl->redirectByClass(
1677  'ilobjcategorygui',
1678  'listUsers'
1679  );
1680  }
1681  }
1682 
1684  int $role_id,
1685  array $roles_of_user,
1686  array $global_roles,
1687  string $import_dir
1688  ): void {
1689  if (in_array(
1690  $role_id,
1691  $global_roles
1692  )) {
1693  if (in_array(
1695  $roles_of_user
1696  )) {
1697  return;
1698  }
1699 
1700  if ($role_id === SYSTEM_ROLE_ID
1701  || $this->object->getRefId() !== USER_FOLDER_ID
1702  && !ilObjRole::_getAssignUsersStatus($role_id)
1703  ) {
1704  $this->filesystem->deleteDir($import_dir);
1705  $this->tpl->setOnScreenMessage(
1706  'failure',
1707  $this->lng->txt('usrimport_with_specified_role_not_permitted'),
1708  true
1709  );
1710  $this->redirectAfterImport();
1711  }
1712  return;
1713  }
1714 
1715  $rolf = $this->rbac_review->getFoldersAssignedToRole(
1716  $role_id,
1717  true
1718  );
1719  if ($this->rbac_review->isDeleted($rolf[0])
1720  || !$this->rbac_system->checkAccess(
1721  'write',
1722  $rolf[0]
1723  )
1724  ) {
1725  $this->filesystem->deleteDir($import_dir);
1726  $this->tpl->setOnScreenMessage(
1727  'failure',
1728  $this->lng->txt('usrimport_with_specified_role_not_permitted'),
1729  true
1730  );
1731  $this->redirectAfterImport();
1732  }
1733  }
1734 
1735  protected function generalSettingsObject(): void
1736  {
1737  $this->raiseErrorOnMissingWrite();
1738  $this->initFormGeneralSettings();
1739 
1741 
1742  $show_blocking_time_in_days = $this->settings->get('loginname_change_blocking_time') / 86400;
1743  $show_blocking_time_in_days = (float) $show_blocking_time_in_days;
1744 
1745  $security = ilSecuritySettings::_getInstance();
1746 
1747  $settings = [
1748  'lua' => $aset->isLocalUserAdministrationEnabled(),
1749  'lrua' => $aset->isUserAccessRestricted(),
1750  'allow_change_loginname' => (bool) $this->settings->get('allow_change_loginname'),
1751  'create_history_loginname' => (bool) $this->settings->get('create_history_loginname'),
1752  'reuse_of_loginnames' => (bool) $this->settings->get('reuse_of_loginnames'),
1753  'loginname_change_blocking_time' => $show_blocking_time_in_days,
1754  'user_reactivate_code' => (int) $this->settings->get('user_reactivate_code'),
1755  'user_own_account' => (int) $this->settings->get('user_delete_own_account'),
1756  'user_own_account_email' => $this->settings->get('user_delete_own_account_email'),
1757  'dpro_withdrawal_usr_deletion' => (bool) $this->settings->get('dpro_withdrawal_usr_deletion'),
1758  'tos_withdrawal_usr_deletion' => (bool) $this->settings->get('tos_withdrawal_usr_deletion'),
1759  'login_max_attempts' => $security->getLoginMaxAttempts() > 0 ? $security->getLoginMaxAttempts() : '',
1760  'ps_prevent_simultaneous_logins' => (int) $security->isPreventionOfSimultaneousLoginsEnabled(),
1761  'password_assistance' => (bool) $this->settings->get('password_assistance'),
1762  'letter_avatars' => (int) $this->settings->get('letter_avatars'),
1763  'password_change_on_first_login_enabled' => $security->isPasswordChangeOnFirstLoginEnabled() ? 1 : 0,
1764  'password_max_age' => $security->getPasswordMaxAge()
1765  ];
1766 
1767  $passwordPolicySettings = $this->getPasswordPolicySettingsMap($security);
1768  $this->form->setValuesByArray(
1769  array_merge(
1770  $settings,
1771  $passwordPolicySettings,
1772  ['pw_policy_hash' => md5(
1773  implode(
1774  '',
1775  $passwordPolicySettings
1776  )
1777  )
1778  ]
1779  )
1780  );
1781 
1782  $this->tpl->setContent($this->form->getHTML());
1783  }
1784 
1785  private function getPasswordPolicySettingsMap(\ilSecuritySettings $security): array // Missing array type.
1786  {
1787  return [
1788  'password_must_not_contain_loginame' => $security->getPasswordMustNotContainLoginnameStatus() ? 1 : 0,
1789  'password_chars_and_numbers_enabled' => $security->isPasswordCharsAndNumbersEnabled() ? 1 : 0,
1790  'password_special_chars_enabled' => $security->isPasswordSpecialCharsEnabled() ? 1 : 0,
1791  'password_min_length' => $security->getPasswordMinLength(),
1792  'password_max_length' => $security->getPasswordMaxLength(),
1793  'password_ucase_chars_num' => $security->getPasswordNumberOfUppercaseChars(),
1794  'password_lowercase_chars_num' => $security->getPasswordNumberOfLowercaseChars(),
1795  ];
1796  }
1797 
1801  public function saveGeneralSettingsObject(): void
1802  {
1803  $this->raiseErrorOnMissingWrite();
1804  $this->initFormGeneralSettings();
1805  if ($this->form->checkInput()) {
1806  $valid = true;
1807  if ($this->form->getInput('allow_change_loginname') === '1' &&
1808  !is_numeric($this->form->getInput('loginname_change_blocking_time'))) {
1809  $valid = false;
1810  $this->form->getItemByPostVar('loginname_change_blocking_time')
1811  ->setAlert($this->lng->txt('loginname_change_blocking_time_invalidity_info'));
1812  }
1813 
1814  $security = ilSecuritySettings::_getInstance();
1815 
1816  // account security settings
1817  $security->setPasswordCharsAndNumbersEnabled(
1818  (bool) $this->form->getInput('password_chars_and_numbers_enabled')
1819  );
1820  $security->setPasswordSpecialCharsEnabled(
1821  (bool) $this->form->getInput('password_special_chars_enabled')
1822  );
1823  $security->setPasswordMinLength(
1824  (int) $this->form->getInput('password_min_length')
1825  );
1826  $security->setPasswordMaxLength(
1827  (int) $this->form->getInput('password_max_length')
1828  );
1829  $security->setPasswordNumberOfUppercaseChars(
1830  (int) $this->form->getInput('password_ucase_chars_num')
1831  );
1832  $security->setPasswordNumberOfLowercaseChars(
1833  (int) $this->form->getInput('password_lowercase_chars_num')
1834  );
1835  $security->setPasswordMaxAge(
1836  (int) $this->form->getInput('password_max_age')
1837  );
1838  $security->setLoginMaxAttempts(
1839  (int) $this->form->getInput('login_max_attempts')
1840  );
1841  $security->setPreventionOfSimultaneousLogins(
1842  (bool) $this->form->getInput('ps_prevent_simultaneous_logins')
1843  );
1844  $security->setPasswordChangeOnFirstLoginEnabled(
1845  (bool) $this->form->getInput('password_change_on_first_login_enabled')
1846  );
1847  $security->setPasswordMustNotContainLoginnameStatus(
1848  (bool) $this->form->getInput('password_must_not_contain_loginame')
1849  );
1850 
1851  if ($security->validate($this->form) !== null) {
1852  $valid = false;
1853  }
1854 
1855  if ($valid) {
1856  $security->save();
1857 
1858  ilUserAccountSettings::getInstance()->enableLocalUserAdministration((bool) $this->form->getInput('lua'));
1859  ilUserAccountSettings::getInstance()->restrictUserAccess((bool) $this->form->getInput('lrua'));
1861 
1862  $this->settings->set(
1863  'allow_change_loginname',
1864  $this->form->getInput('allow_change_loginname')
1865  );
1866  $this->settings->set(
1867  'create_history_loginname',
1868  $this->form->getInput('create_history_loginname')
1869  );
1870  $this->settings->set(
1871  'reuse_of_loginnames',
1872  $this->form->getInput('reuse_of_loginnames')
1873  );
1874  $save_blocking_time_in_seconds = (string) ((int) $this->form->getInput(
1875  'loginname_change_blocking_time'
1876  ) * 86400);
1877  $this->settings->set(
1878  'loginname_change_blocking_time',
1879  $save_blocking_time_in_seconds
1880  );
1881  $this->settings->set(
1882  'user_reactivate_code',
1883  $this->form->getInput('user_reactivate_code')
1884  );
1885 
1886  $this->settings->set(
1887  'user_delete_own_account',
1888  $this->form->getInput('user_own_account')
1889  );
1890  $this->settings->set(
1891  'user_delete_own_account_email',
1892  $this->form->getInput('user_own_account_email')
1893  );
1894  $this->settings->set(
1895  'dpro_withdrawal_usr_deletion',
1896  $this->form->getInput('dpro_withdrawal_usr_deletion') === '1' ? '1' : '0'
1897  );
1898  $this->settings->set(
1899  'tos_withdrawal_usr_deletion',
1900  $this->form->getInput('tos_withdrawal_usr_deletion') === '1' ? '1' : '0'
1901  );
1902 
1903  $this->settings->set(
1904  'password_assistance',
1905  $this->form->getInput('password_assistance')
1906  );
1907 
1908  $this->settings->set(
1909  'letter_avatars',
1910  $this->form->getInput('letter_avatars')
1911  );
1912 
1913  $requestPasswordReset = false;
1914  if ($this->form->getInput('pw_policy_hash')) {
1915  $oldSettingsHash = $this->form->getInput('pw_policy_hash');
1916  $currentSettingsHash = md5(
1917  implode(
1918  '',
1919  $this->getPasswordPolicySettingsMap($security)
1920  )
1921  );
1922  $requestPasswordReset = ($oldSettingsHash !== $currentSettingsHash);
1923  }
1924 
1925  if ($requestPasswordReset) {
1926  $this->ctrl->redirect(
1927  $this,
1928  'askForUserPasswordReset'
1929  );
1930  } else {
1931  $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'));
1932  }
1933  } else {
1934  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
1935  }
1936  } else {
1937  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
1938  }
1939  $this->form->setValuesByPost();
1940  $this->tpl->setContent($this->form->getHTML());
1941  }
1942 
1943  protected function forceUserPasswordResetObject(): void
1944  {
1945  LocalUserPasswordManager::getInstance()->resetLastPasswordChangeForLocalUsers();
1946  $this->lng->loadLanguageModule('ps');
1947 
1948  $this->tpl->setOnScreenMessage('success', $this->lng->txt('ps_passwd_policy_change_force_user_reset_succ'), true);
1949  $this->ctrl->redirect(
1950  $this,
1951  'generalSettings'
1952  );
1953  }
1954 
1955  protected function askForUserPasswordResetObject(): void
1956  {
1957  $this->lng->loadLanguageModule('ps');
1958 
1959  $this->tpl->setOnScreenMessage(
1960  'question',
1961  $this->lng->txt('ps_passwd_policy_changed_force_user_reset')
1962  );
1963 
1964  $this->toolbar->addComponent(
1965  $this->ui_factory->button()->standard(
1966  $this->lng->txt('yes'),
1967  $this->ctrl->getLinkTargetByClass(self::class, 'forceUserPasswordReset')
1968  )
1969  );
1970 
1971  $this->toolbar->addComponent(
1972  $this->ui_factory->button()->standard(
1973  $this->lng->txt('no'),
1974  $this->ctrl->getLinkTargetByClass(self::class, 'generalSettings')
1975  )
1976  );
1977  }
1978 
1979  protected function initFormGeneralSettings(): void
1980  {
1981  $this->setSubTabs('settings');
1982  $this->tabs_gui->setTabActive('settings');
1983  $this->tabs_gui->setSubTabActive('general_settings');
1984 
1985  $this->form = new ilPropertyFormGUI();
1986  $this->form->setFormAction(
1987  $this->ctrl->getFormAction(
1988  $this,
1989  'saveGeneralSettings'
1990  )
1991  );
1992 
1993  $this->form->setTitle($this->lng->txt('general_settings'));
1994 
1995  $lua = new ilCheckboxInputGUI(
1996  $this->lng->txt('enable_local_user_administration'),
1997  'lua'
1998  );
1999  $lua->setInfo($this->lng->txt('enable_local_user_administration_info'));
2000  $lua->setValue('1');
2001  $this->form->addItem($lua);
2002 
2003  $lrua = new ilCheckboxInputGUI(
2004  $this->lng->txt('restrict_user_access'),
2005  'lrua'
2006  );
2007  $lrua->setInfo($this->lng->txt('restrict_user_access_info'));
2008  $lrua->setValue('1');
2009  $this->form->addItem($lrua);
2010 
2011  $code = new ilCheckboxInputGUI(
2012  $this->lng->txt('user_account_code_setting'),
2013  'user_reactivate_code'
2014  );
2015  $code->setInfo($this->lng->txt('user_account_code_setting_info'));
2016  $this->form->addItem($code);
2017 
2018  $own = new ilCheckboxInputGUI(
2019  $this->lng->txt('user_allow_delete_own_account'),
2020  'user_own_account'
2021  );
2022  $this->form->addItem($own);
2023  $own_email = new ilEMailInputGUI(
2024  $this->lng->txt('user_delete_own_account_notification_email'),
2025  'user_own_account_email'
2026  );
2027  $own->addSubItem($own_email);
2028 
2029  $this->lng->loadLanguageModule('tos');
2030  $this->lng->loadLanguageModule('dpro');
2031  $this->form->addItem($this->checkbox('tos_withdrawal_usr_deletion'));
2032  $this->form->addItem($this->checkbox('dpro_withdrawal_usr_deletion'));
2033 
2034  $allow_client_maintenance = $this->settings->get(
2035  'session_allow_client_maintenance',
2037  );
2038 
2039  $this->lng->loadLanguageModule('ps');
2040 
2041  $pass = new ilFormSectionHeaderGUI();
2042  $pass->setTitle($this->lng->txt('ps_password_settings'));
2043  $this->form->addItem($pass);
2044 
2045  $check = new ilCheckboxInputGUI(
2046  $this->lng->txt('ps_password_change_on_first_login_enabled'),
2047  'password_change_on_first_login_enabled'
2048  );
2049  $check->setInfo($this->lng->txt('ps_password_change_on_first_login_enabled_info'));
2050  $this->form->addItem($check);
2051 
2052  $check = new ilCheckboxInputGUI(
2053  $this->lng->txt('ps_password_must_not_contain_loginame'),
2054  'password_must_not_contain_loginame'
2055  );
2056  $check->setInfo($this->lng->txt('ps_password_must_not_contain_loginame_info'));
2057  $this->form->addItem($check);
2058 
2059  $check = new ilCheckboxInputGUI(
2060  $this->lng->txt('ps_password_chars_and_numbers_enabled'),
2061  'password_chars_and_numbers_enabled'
2062  );
2063  //$check->setOptionTitle($this->lng->txt('ps_password_chars_and_numbers_enabled'));
2064  $check->setInfo($this->lng->txt('ps_password_chars_and_numbers_enabled_info'));
2065  $this->form->addItem($check);
2066 
2067  $check = new ilCheckboxInputGUI(
2068  $this->lng->txt('ps_password_special_chars_enabled'),
2069  'password_special_chars_enabled'
2070  );
2071  //$check->setOptionTitle($this->lng->txt('ps_password_special_chars_enabled'));
2072  $check->setInfo($this->lng->txt('ps_password_special_chars_enabled_info'));
2073  $this->form->addItem($check);
2074 
2075  $text = new ilNumberInputGUI(
2076  $this->lng->txt('ps_password_min_length'),
2077  'password_min_length'
2078  );
2079  $text->setInfo($this->lng->txt('ps_password_min_length_info'));
2080  $text->setSize(1);
2081  $text->setMaxLength(2);
2082  $this->form->addItem($text);
2083 
2084  $text = new ilNumberInputGUI(
2085  $this->lng->txt('ps_password_max_length'),
2086  'password_max_length'
2087  );
2088  $text->setInfo($this->lng->txt('ps_password_max_length_info'));
2089  $text->setSize(2);
2090  $text->setMaxLength(3);
2091  $this->form->addItem($text);
2092 
2093  $text = new ilNumberInputGUI(
2094  $this->lng->txt('ps_password_uppercase_chars_num'),
2095  'password_ucase_chars_num'
2096  );
2097  $text->setInfo($this->lng->txt('ps_password_uppercase_chars_num_info'));
2098  $text->setMinValue(0);
2099  $text->setSize(2);
2100  $text->setMaxLength(3);
2101  $this->form->addItem($text);
2102 
2103  $text = new ilNumberInputGUI(
2104  $this->lng->txt('ps_password_lowercase_chars_num'),
2105  'password_lowercase_chars_num'
2106  );
2107  $text->setInfo($this->lng->txt('ps_password_lowercase_chars_num_info'));
2108  $text->setMinValue(0);
2109  $text->setSize(2);
2110  $text->setMaxLength(3);
2111  $this->form->addItem($text);
2112 
2113  $text = new ilNumberInputGUI(
2114  $this->lng->txt('ps_password_max_age'),
2115  'password_max_age'
2116  );
2117  $text->setInfo($this->lng->txt('ps_password_max_age_info'));
2118  $text->setSize(2);
2119  $text->setMaxLength(3);
2120  $this->form->addItem($text);
2121 
2122  // password assistance
2123  $cb = new ilCheckboxInputGUI(
2124  $this->lng->txt('enable_password_assistance'),
2125  'password_assistance'
2126  );
2127  $cb->setInfo($this->lng->txt('password_assistance_info'));
2128  $this->form->addItem($cb);
2129 
2130  $pass = new ilFormSectionHeaderGUI();
2131  $pass->setTitle($this->lng->txt('ps_security_protection'));
2132  $this->form->addItem($pass);
2133 
2134  $text = new ilNumberInputGUI(
2135  $this->lng->txt('ps_login_max_attempts'),
2136  'login_max_attempts'
2137  );
2138  $text->setInfo($this->lng->txt('ps_login_max_attempts_info'));
2139  $text->allowDecimals(false);
2140  $text->setMinValue(1);
2142  $text->setSize(1);
2143  $text->setMaxLength(2);
2144  $this->form->addItem($text);
2145 
2146  // prevent login from multiple pcs at the same time
2147  $objCb = new ilCheckboxInputGUI(
2148  $this->lng->txt('ps_prevent_simultaneous_logins'),
2149  'ps_prevent_simultaneous_logins'
2150  );
2151  $objCb->setValue('1');
2152  $objCb->setInfo($this->lng->txt('ps_prevent_simultaneous_logins_info'));
2153  $this->form->addItem($objCb);
2154 
2155  $log = new ilFormSectionHeaderGUI();
2156  $log->setTitle($this->lng->txt('loginname_settings'));
2157  $this->form->addItem($log);
2158 
2159  $chbChangeLogin = new ilCheckboxInputGUI(
2160  $this->lng->txt('allow_change_loginname'),
2161  'allow_change_loginname'
2162  );
2163  $chbChangeLogin->setValue('1');
2164  $this->form->addItem($chbChangeLogin);
2165  $chbCreateHistory = new ilCheckboxInputGUI(
2166  $this->lng->txt('history_loginname'),
2167  'create_history_loginname'
2168  );
2169  $chbCreateHistory->setInfo($this->lng->txt('loginname_history_info'));
2170  $chbCreateHistory->setValue('1');
2171 
2172  $chbChangeLogin->addSubItem($chbCreateHistory);
2173  $chbReuseLoginnames = new ilCheckboxInputGUI(
2174  $this->lng->txt('reuse_of_loginnames_contained_in_history'),
2175  'reuse_of_loginnames'
2176  );
2177  $chbReuseLoginnames->setValue('1');
2178  $chbReuseLoginnames->setInfo($this->lng->txt('reuse_of_loginnames_contained_in_history_info'));
2179 
2180  $chbChangeLogin->addSubItem($chbReuseLoginnames);
2181  $chbChangeBlockingTime = new ilNumberInputGUI(
2182  $this->lng->txt('loginname_change_blocking_time'),
2183  'loginname_change_blocking_time'
2184  );
2185  $chbChangeBlockingTime->allowDecimals(true);
2186  $chbChangeBlockingTime->setSuffix($this->lng->txt('days'));
2187  $chbChangeBlockingTime->setInfo($this->lng->txt('loginname_change_blocking_time_info'));
2188  $chbChangeBlockingTime->setSize(10);
2189  $chbChangeBlockingTime->setMaxLength(10);
2190  $chbChangeLogin->addSubItem($chbChangeBlockingTime);
2191 
2192  $la = new ilCheckboxInputGUI(
2193  $this->lng->txt('usr_letter_avatars'),
2194  'letter_avatars'
2195  );
2196  $la->setValue('1');
2197  $la->setInfo($this->lng->txt('usr_letter_avatars_info'));
2198  $this->form->addItem($la);
2199 
2200  $passwordPolicySettingsHash = new \ilHiddenInputGUI('pw_policy_hash');
2201  $this->form->addItem($passwordPolicySettingsHash);
2202 
2203  $this->form->addCommandButton(
2204  'saveGeneralSettings',
2205  $this->lng->txt('save')
2206  );
2207  }
2208 
2217  public function settingsObject(): void
2218  {
2219  $this->raiseErrorOnMissingWrite();
2220 
2221  $this->lng->loadLanguageModule('administration');
2222  $this->lng->loadLanguageModule('mail');
2223  $this->lng->loadLanguageModule('chatroom');
2224  $this->setSubTabs('settings');
2225  $this->tabs_gui->activateTab('settings');
2226  $this->tabs_gui->activateSubTab('standard_fields');
2227 
2228  $tab = new ilUserFieldSettingsTableGUI(
2229  $this,
2230  'settings'
2231  );
2232  if ($this->confirm_change) {
2233  $tab->setConfirmChange();
2234  }
2235  $this->tpl->setContent($tab->getHTML());
2236  }
2237 
2238  public function confirmSavedObject(): void
2239  {
2240  $this->raiseErrorOnMissingWrite();
2241  $this->saveGlobalUserSettingsObject('save');
2242  }
2243 
2244  public function saveGlobalUserSettingsObject(string $action = ''): void
2245  {
2246  $this->raiseErrorOnMissingWrite();
2247 
2248  $checked = $this->user_request->getChecked();
2249  $selected = $this->user_request->getSelect();
2250 
2251  $user_settings_config = $this->user_settings_config;
2252 
2253  // see ilUserFieldSettingsTableGUI
2254  $up = new ilUserProfile();
2255  $up->skipField('username');
2256  $field_properties = $up->getStandardFields();
2257  $profile_fields = array_keys($field_properties);
2258 
2259  $valid = true;
2260  foreach ($profile_fields as $field) {
2261  if (($checked['required_' . $field] ?? false) &&
2262  !(int) ($checked['visib_reg_' . $field] ?? null)
2263  ) {
2264  $valid = false;
2265  break;
2266  }
2267  }
2268 
2269  if (!$valid) {
2270  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('invalid_visible_required_options_selected'));
2271  $this->confirm_change = 1;
2272  $this->settingsObject();
2273  return;
2274  }
2275 
2276  // For the following fields, the required state can not be changed
2277  $fixed_required_fields = [
2278  'firstname' => 1,
2279  'lastname' => 1,
2280  'upload' => 0,
2281  'password' => 0,
2282  'language' => 0,
2283  'skin_style' => 0,
2284  'hide_own_online_status' => 0
2285  ];
2286 
2287  // Reset user confirmation
2288  if ($action == 'save') {
2290  }
2291 
2292  $changed_fields = $this->collectChangedFields();
2293  if ($this->handleChangeListeners($changed_fields, $field_properties)) {
2294  return;
2295  }
2296 
2297  foreach ($profile_fields as $field) {
2298  // Enable disable searchable
2299  if (ilUserSearchOptions::_isSearchable($field)) {
2301  $field,
2302  (bool) ($checked['searchable_' . $field] ?? false)
2303  );
2304  }
2305 
2306  if (!($checked['visible_' . $field] ?? false) && !($field_properties[$field]['visible_hide'] ?? false)) {
2307  $user_settings_config->setVisible(
2308  $field,
2309  false
2310  );
2311  } else {
2312  $user_settings_config->setVisible(
2313  $field,
2314  true
2315  );
2316  }
2317 
2318  if (!($checked['changeable_' . $field] ?? false) &&
2319  !($field_properties[$field]['changeable_hide'] ?? false)) {
2320  $user_settings_config->setChangeable(
2321  $field,
2322  false
2323  );
2324  } else {
2325  $user_settings_config->setChangeable(
2326  $field,
2327  true
2328  );
2329  }
2330 
2331  // registration visible
2332  if (($checked['visib_reg_' . $field] ?? false) && !($field_properties[$field]['visib_reg_hide'] ?? false)) {
2333  $this->settings->set(
2334  'usr_settings_visib_reg_' . $field,
2335  '1'
2336  );
2337  } else {
2338  $this->settings->set(
2339  'usr_settings_visib_reg_' . $field,
2340  '0'
2341  );
2342  }
2343 
2344  if ($checked['visib_lua_' . $field] ?? false) {
2345  $this->settings->set(
2346  'usr_settings_visib_lua_' . $field,
2347  '1'
2348  );
2349  } else {
2350  $this->settings->set(
2351  'usr_settings_visib_lua_' . $field,
2352  '0'
2353  );
2354  }
2355 
2356  if ((int) ($checked['changeable_lua_' . $field] ?? false)) {
2357  $this->settings->set(
2358  'usr_settings_changeable_lua_' . $field,
2359  '1'
2360  );
2361  } else {
2362  $this->settings->set(
2363  'usr_settings_changeable_lua_' . $field,
2364  '0'
2365  );
2366  }
2367 
2368  if (($checked['export_' . $field] ?? false) && !($field_properties[$field]['export_hide'] ?? false)) {
2369  $this->ilias->setSetting(
2370  'usr_settings_export_' . $field,
2371  '1'
2372  );
2373  } else {
2374  $this->ilias->deleteSetting('usr_settings_export_' . $field);
2375  }
2376 
2377  // Course export/visibility
2378  if (($checked['course_export_' . $field] ?? false) && !($field_properties[$field]['course_export_hide'] ?? false)) {
2379  $this->ilias->setSetting(
2380  'usr_settings_course_export_' . $field,
2381  '1'
2382  );
2383  } else {
2384  $this->ilias->deleteSetting('usr_settings_course_export_' . $field);
2385  }
2386 
2387  // Group export/visibility
2388  if (($checked['group_export_' . $field] ?? false) && !($field_properties[$field]['group_export_hide'] ?? false)) {
2389  $this->ilias->setSetting(
2390  'usr_settings_group_export_' . $field,
2391  '1'
2392  );
2393  } else {
2394  $this->ilias->deleteSetting('usr_settings_group_export_' . $field);
2395  }
2396 
2397  if (($checked['prg_export_' . $field] ?? false) && !($field_properties[$field]['prg_export_hide'] ?? false)) {
2398  $this->ilias->setSetting(
2399  'usr_settings_prg_export_' . $field,
2400  '1'
2401  );
2402  } else {
2403  $this->ilias->deleteSetting('usr_settings_prg_export_' . $field);
2404  }
2405 
2406  $is_fixed = array_key_exists(
2407  $field,
2408  $fixed_required_fields
2409  );
2410  if (($is_fixed && $fixed_required_fields[$field]) || (!$is_fixed && ($checked['required_' . $field] ?? false))) {
2411  $this->ilias->setSetting(
2412  'require_' . $field,
2413  '1'
2414  );
2415  } else {
2416  $this->ilias->deleteSetting('require_' . $field);
2417  }
2418  }
2419 
2420  $this->ilias->setSetting(
2421  'session_reminder_lead_time',
2422  $this->user_request->getDefaultSessionReminder()
2423  );
2424 
2425  if (isset($checked['export_preferences']) && $checked['export_preferences'] === 1) {
2426  $this->ilias->setSetting(
2427  'usr_settings_export_preferences',
2428  '1'
2429  );
2430  } else {
2431  $this->ilias->deleteSetting('usr_settings_export_preferences');
2432  }
2433 
2434  $this->ilias->setSetting(
2435  'mail_incoming_mail',
2436  $selected['default_mail_incoming_mail'] ?? '0'
2437  );
2438  $this->ilias->setSetting(
2439  'chat_osc_accept_msg',
2440  $selected['default_chat_osc_accept_msg'] ?? 'n'
2441  );
2442  $this->ilias->setSetting(
2443  'chat_broadcast_typing',
2444  $selected['default_chat_broadcast_typing'] ?? 'n'
2445  );
2446  $this->ilias->setSetting(
2447  'bs_allow_to_contact_me',
2448  $selected['default_bs_allow_to_contact_me'] ?? 'n'
2449  );
2450  $this->ilias->setSetting(
2451  'hide_own_online_status',
2452  $selected['default_hide_own_online_status'] ?? 'n'
2453  );
2454 
2455  if ($this->usrFieldChangeListenersAccepted && count($changed_fields) > 0) {
2456  $this->event->raise(
2457  'components/ILIAS/User',
2458  'onUserFieldAttributesChanged',
2459  $changed_fields
2460  );
2461  }
2462 
2463  $this->tpl->setOnScreenMessage('success', $this->lng->txt('usr_settings_saved'));
2464  $this->settingsObject();
2465  }
2466 
2468  {
2469  $this->usrFieldChangeListenersAccepted = true;
2470  $this->confirmSavedObject();
2471  }
2472 
2477  array $interested_change_listeners
2478  ): void {
2479  $post = $this->user_request->getParsedBody();
2480  $confirmDialog = new ilConfirmationGUI();
2481  $confirmDialog->setHeaderText($this->lng->txt('usr_field_change_components_listening'));
2482  $confirmDialog->setFormAction($this->ctrl->getFormActionByClass(
2483  [self::class],
2484  'settings'
2485  ));
2486  $confirmDialog->setConfirm($this->lng->txt('confirm'), 'confirmUsrFieldChangeListeners');
2487  $confirmDialog->setCancel($this->lng->txt('cancel'), 'settings');
2488 
2489  $tpl = new ilTemplate(
2490  'tpl.usr_field_change_listener_confirm.html',
2491  true,
2492  true,
2493  'components/ILIAS/User'
2494  );
2495 
2496  foreach ($interested_change_listeners as $interested_change_listener) {
2497  $tpl->setVariable('FIELD_NAME', $interested_change_listener->getName());
2498  foreach ($interested_change_listener->getAttributes() as $attribute) {
2499  $tpl->setVariable('ATTRIBUTE_NAME', $attribute->getName());
2500  foreach ($attribute->getComponents() as $component) {
2501  $tpl->setVariable('COMPONENT_NAME', $component->getComponentName());
2502  $tpl->setVariable('DESCRIPTION', $component->getDescription());
2503  $tpl->setCurrentBlock('component');
2504  $tpl->parseCurrentBlock('component');
2505  }
2506  $tpl->setCurrentBlock('attribute');
2507  $tpl->parseCurrentBlock('attribute');
2508  }
2509  $tpl->setCurrentBlock('field');
2510  $tpl->parseCurrentBlock('field');
2511  }
2512 
2513  $confirmDialog->addItem('', '0', $tpl->get());
2514 
2515  foreach ($post['chb'] as $postVar => $value) {
2516  $confirmDialog->addHiddenItem("chb[{$postVar}]", $value);
2517  }
2518  foreach ($post['select'] as $postVar => $value) {
2519  $confirmDialog->addHiddenItem("select[{$postVar}]", $value);
2520  }
2521  foreach ($post['current'] as $postVar => $value) {
2522  $confirmDialog->addHiddenItem("current[{$postVar}]", $value);
2523  }
2524  $this->tpl->setContent($confirmDialog->getHTML());
2525  }
2526 
2532  private function handleChangeListeners(
2533  array $changed_fields,
2534  array $field_properties
2535  ): bool {
2536  if (count($changed_fields) > 0) {
2537  $interested_change_listeners = [];
2538  foreach ($field_properties as $field_name => $properties) {
2539  if (!isset($properties['change_listeners'])) {
2540  continue;
2541  }
2542 
2543  foreach ($properties['change_listeners'] as $change_listener_class_name) {
2547  $listener = new $change_listener_class_name($this->dic);
2548  foreach ($changed_fields as $changed_field) {
2549  $attribute_name = $changed_field->getAttributeName();
2550  $description_for_field = $listener->getDescriptionForField($field_name, $attribute_name);
2551  if ($description_for_field !== null && $description_for_field !== '') {
2552  $interested_change_listener = null;
2553  foreach ($interested_change_listeners as $interested_listener) {
2554  if ($interested_listener->getFieldName() === $field_name) {
2555  $interested_change_listener = $interested_listener;
2556  break;
2557  }
2558  }
2559 
2560  if ($interested_change_listener === null) {
2561  $interested_change_listener = new InterestedUserFieldChangeListener(
2562  $this->lng,
2563  $this->getTranslationForField($field_name, $properties),
2564  $field_name
2565  );
2566  $interested_change_listeners[] = $interested_change_listener;
2567  }
2568 
2569  $interested_attribute = $interested_change_listener->addAttribute($attribute_name);
2570  $interested_attribute->addComponent(
2571  $listener->getComponentName(),
2572  $description_for_field
2573  );
2574  }
2575  }
2576  }
2577  }
2578 
2579  if (!$this->usrFieldChangeListenersAccepted && count($interested_change_listeners) > 0) {
2580  $this->showFieldChangeComponentsListeningConfirmDialog($interested_change_listeners);
2581  return true;
2582  }
2583  }
2584 
2585  return false;
2586  }
2587 
2591  private function collectChangedFields(): array
2592  {
2593  $changed_fields = [];
2594  $post = $this->user_request->getParsedBody();
2595  if (
2596  !isset($post['chb'])
2597  && !is_array($post['chb'])
2598  && !isset($post['current'])
2599  && !is_array($post['current'])
2600  ) {
2601  return $changed_fields;
2602  }
2603 
2604  $old = $post['current'];
2605  $new = $post['chb'];
2606 
2607  foreach ($old as $key => $old_value) {
2608  if (!isset($new[$key])) {
2609  $is_boolean = filter_var($old_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
2610  $new[$key] = $is_boolean ? '0' : $old_value;
2611  }
2612  }
2613 
2614  $oldToNewDiff = array_diff_assoc($old, $new);
2615 
2616  foreach ($oldToNewDiff as $key => $old_value) {
2617  $changed_fields[$key] = new ChangedUserFieldAttribute($key, $old_value, $new[$key]);
2618  }
2619 
2620  return $changed_fields;
2621  }
2622 
2626  public function __buildUserFilterSelect(): string
2627  {
2628  $action[-1] = $this->lng->txt('all_users');
2629  $action[1] = $this->lng->txt('usr_active_only');
2630  $action[0] = $this->lng->txt('usr_inactive_only');
2631  $action[2] = $this->lng->txt('usr_limited_access_only');
2632  $action[3] = $this->lng->txt('usr_without_courses');
2633  $action[4] = $this->lng->txt('usr_filter_lastlogin');
2634  $action[5] = $this->lng->txt('usr_filter_coursemember');
2635  $action[6] = $this->lng->txt('usr_filter_groupmember');
2636  $action[7] = $this->lng->txt('usr_filter_role');
2637 
2639  ilSession::get('user_filter'),
2640  'user_filter',
2641  $action,
2642  false,
2643  true
2644  );
2645  }
2646 
2651  public function downloadExportFileObject(): void
2652  {
2653  $files = $this->user_request->getFiles();
2654  if (count($files) == 0) {
2655  $this->ilias->raiseError(
2656  $this->lng->txt('no_checkbox'),
2657  $this->ilias->error_obj->MESSAGE
2658  );
2659  }
2660 
2661  if (count($files) > 1) {
2662  $this->ilias->raiseError(
2663  $this->lng->txt('select_max_one_item'),
2664  $this->ilias->error_obj->MESSAGE
2665  );
2666  }
2667 
2668  $file = basename($files[0]);
2669 
2670  $export_dir = $this->object->getExportDirectory();
2672  $export_dir . '/' . $file,
2673  $file
2674  );
2675  }
2676 
2677  public function confirmDeleteExportFileObject(): void
2678  {
2679  $files = $this->user_request->getFiles();
2680  if (count($files) == 0) {
2681  $this->ilias->raiseError(
2682  $this->lng->txt('no_checkbox'),
2683  $this->ilias->error_obj->MESSAGE
2684  );
2685  }
2686 
2687  $cgui = new ilConfirmationGUI();
2688  $cgui->setFormAction($this->ctrl->getFormAction($this));
2689  $cgui->setHeaderText($this->lng->txt('info_delete_sure'));
2690  $cgui->setCancel(
2691  $this->lng->txt('cancel'),
2692  'cancelDeleteExportFile'
2693  );
2694  $cgui->setConfirm(
2695  $this->lng->txt('confirm'),
2696  'deleteExportFile'
2697  );
2698 
2699  // BEGIN TABLE DATA
2700  foreach ($files as $file) {
2701  $cgui->addItem(
2702  'file[]',
2703  $file,
2704  $file,
2705  ilObject::_getIcon($this->object->getId()),
2706  $this->lng->txt('obj_usrf')
2707  );
2708  }
2709 
2710  $this->tpl->setContent($cgui->getHTML());
2711  }
2712 
2713  public function cancelDeleteExportFileObject(): void
2714  {
2715  $this->ctrl->redirectByClass(
2716  'ilobjuserfoldergui',
2717  'export'
2718  );
2719  }
2720 
2721  public function deleteExportFileObject(): void
2722  {
2723  $this->raiseErrorOnMissingWrite();
2724  $files = $this->user_request->getFiles();
2725  $export_dir = $this->object->getExportDirectory();
2726  foreach ($files as $file) {
2727  $file = basename($file);
2728 
2729  $exp_file = $export_dir . '/' . $file;
2730  if (is_file($exp_file)) {
2731  unlink($exp_file);
2732  }
2733  }
2734  $this->ctrl->redirectByClass(
2735  'ilobjuserfoldergui',
2736  'export'
2737  );
2738  }
2739 
2744  protected function performExportObject(): void
2745  {
2746  $this->checkPermission('write,read_users');
2747 
2748  $this->object->buildExportFile($this->user_request->getExportType());
2749  $this->ctrl->redirect(
2750  $this,
2751  'export'
2752  );
2753  }
2754 
2755  public function exportObject(): void
2756  {
2757  $this->checkPermission('write,read_users');
2758 
2759  $export_types = [
2760  'userfolder_export_excel_x86',
2761  'userfolder_export_csv',
2762  'userfolder_export_xml'
2763  ];
2764  $options = [];
2765  foreach ($export_types as $type) {
2766  $this->ctrl->setParameterByClass(self::class, 'export_type', $type);
2767  $options[] = $this->ui_factory->button()->shy(
2768  $this->lng->txt($type),
2769  $this->ctrl->getLinkTargetByClass(self::class, 'performExport')
2770  );
2771  }
2772  $type_selection = $this->ui_factory->dropdown()->standard($options)
2773  ->withLabel($this->lng->txt('create_export_file'));
2774 
2775  $this->toolbar->addComponent(
2776  $type_selection,
2777  true
2778  );
2779 
2780  $table = new \ilUserExportFileTableGUI(
2781  $this,
2782  'export'
2783  );
2784  $table->init();
2785  $table->parse($this->object->getExportFiles());
2786 
2787  $this->tpl->setContent($table->getHTML());
2788  }
2789 
2791  {
2792  $this->lng->loadLanguageModule('meta');
2793  $this->lng->loadLanguageModule('mail');
2794 
2795  $form = new ilPropertyFormGUI();
2796  $form->setFormAction($this->ctrl->getFormAction($this));
2797 
2798  $form->setTitleIcon(ilUtil::getImagePath('standard/icon_mail.svg'));
2799  $form->setTitle($this->lng->txt('user_new_account_mail'));
2800  $form->setDescription($this->lng->txt('user_new_account_mail_desc'));
2801 
2802  $langs = $this->lng->getInstalledLanguages();
2803  foreach ($langs as $lang_key) {
2804  $amail = ilObjUserFolder::_lookupNewAccountMail($lang_key);
2805 
2806  $title = $this->lng->txt('meta_l_' . $lang_key);
2807  if ($lang_key == $this->lng->getDefaultLanguage()) {
2808  $title .= ' (' . $this->lng->txt('default') . ')';
2809  }
2810 
2811  $header = new ilFormSectionHeaderGUI();
2812  $header->setTitle($title);
2813  $form->addItem($header);
2814 
2815  $subj = new ilTextInputGUI(
2816  $this->lng->txt('subject'),
2817  'subject_' . $lang_key
2818  );
2819  $subj->setValue($amail['subject'] ?? '');
2820  $form->addItem($subj);
2821 
2822  $salg = new ilTextInputGUI(
2823  $this->lng->txt('mail_salutation_general'),
2824  'sal_g_' . $lang_key
2825  );
2826  $salg->setValue($amail['sal_g'] ?? '');
2827  $form->addItem($salg);
2828 
2829  $salf = new ilTextInputGUI(
2830  $this->lng->txt('mail_salutation_female'),
2831  'sal_f_' . $lang_key
2832  );
2833  $salf->setValue($amail['sal_f'] ?? '');
2834  $form->addItem($salf);
2835 
2836  $salm = new ilTextInputGUI(
2837  $this->lng->txt('mail_salutation_male'),
2838  'sal_m_' . $lang_key
2839  );
2840  $salm->setValue($amail['sal_m'] ?? '');
2841  $form->addItem($salm);
2842 
2843  $body = new ilTextAreaInputGUI(
2844  $this->lng->txt('message_content'),
2845  'body_' . $lang_key
2846  );
2847  $body->setValue($amail['body'] ?? '');
2848  $body->setRows(10);
2849  $body->setCols(100);
2850  $form->addItem($body);
2851 
2852  $att = new ilFileInputGUI(
2853  $this->lng->txt('attachment'),
2854  'att_' . $lang_key
2855  );
2856  $att->setAllowDeletion(true);
2857  if ($amail['att_file'] ?? false) {
2858  $att->setValue($amail['att_file']);
2859  }
2860  $form->addItem($att);
2861  }
2862 
2863  $form->addCommandButton(
2864  'saveNewAccountMail',
2865  $this->lng->txt('save')
2866  );
2867  $form->addCommandButton(
2868  'cancelNewAccountMail',
2869  $this->lng->txt('cancel')
2870  );
2871 
2872  return $form;
2873  }
2874 
2875  public function newAccountMailObject(ilPropertyFormGUI $form = null): void
2876  {
2877  $this->raiseErrorOnMissingWrite();
2878  $this->setSubTabs('settings');
2879  $this->tabs_gui->setTabActive('settings');
2880  $this->tabs_gui->setSubTabActive('user_new_account_mail');
2881 
2882  if ($form === null) {
2883  $form = $this->initNewAccountMailForm();
2884  }
2885 
2886  $ftpl = new ilTemplate(
2887  'tpl.usrf_new_account_mail.html',
2888  true,
2889  true,
2890  'components/ILIAS/User'
2891  );
2892  $ftpl->setVariable(
2893  'FORM',
2894  $form->getHTML()
2895  );
2896 
2897  // placeholder help text
2898  $ftpl->setVariable(
2899  'TXT_USE_PLACEHOLDERS',
2900  $this->lng->txt('mail_nacc_use_placeholder')
2901  );
2902  $ftpl->setVariable(
2903  'TXT_MAIL_SALUTATION',
2904  $this->lng->txt('mail_nacc_salutation')
2905  );
2906  $ftpl->setVariable(
2907  'TXT_FIRST_NAME',
2908  $this->lng->txt('firstname')
2909  );
2910  $ftpl->setVariable(
2911  'TXT_LAST_NAME',
2912  $this->lng->txt('lastname')
2913  );
2914  $ftpl->setVariable(
2915  'TXT_EMAIL',
2916  $this->lng->txt('email')
2917  );
2918  $ftpl->setVariable(
2919  'TXT_LOGIN',
2920  $this->lng->txt('mail_nacc_login')
2921  );
2922  $ftpl->setVariable(
2923  'TXT_PASSWORD',
2924  $this->lng->txt('password')
2925  );
2926  $ftpl->setVariable(
2927  'TXT_PASSWORD_BLOCK',
2928  $this->lng->txt('mail_nacc_pw_block')
2929  );
2930  $ftpl->setVariable(
2931  'TXT_NOPASSWORD_BLOCK',
2932  $this->lng->txt('mail_nacc_no_pw_block')
2933  );
2934  $ftpl->setVariable(
2935  'TXT_ADMIN_MAIL',
2936  $this->lng->txt('mail_nacc_admin_mail')
2937  );
2938  $ftpl->setVariable(
2939  'TXT_ILIAS_URL',
2940  $this->lng->txt('mail_nacc_ilias_url')
2941  );
2942  $ftpl->setVariable(
2943  'TXT_INSTALLATION_NAME',
2944  $this->lng->txt('mail_nacc_installation_name')
2945  );
2946  $ftpl->setVariable(
2947  'TXT_TARGET',
2948  $this->lng->txt('mail_nacc_target')
2949  );
2950  $ftpl->setVariable(
2951  'TXT_TARGET_TITLE',
2952  $this->lng->txt('mail_nacc_target_title')
2953  );
2954  $ftpl->setVariable(
2955  'TXT_TARGET_TYPE',
2956  $this->lng->txt('mail_nacc_target_type')
2957  );
2958  $ftpl->setVariable(
2959  'TXT_TARGET_BLOCK',
2960  $this->lng->txt('mail_nacc_target_block')
2961  );
2962  $ftpl->setVariable(
2963  'TXT_IF_TIMELIMIT',
2964  $this->lng->txt('mail_nacc_if_timelimit')
2965  );
2966  $ftpl->setVariable(
2967  'TXT_TIMELIMIT',
2968  $this->lng->txt('mail_nacc_timelimit')
2969  );
2970 
2971  $this->tpl->setContent($ftpl->get());
2972  }
2973 
2974  public function cancelNewAccountMailObject(): void
2975  {
2976  $this->ctrl->redirect(
2977  $this,
2978  'settings'
2979  );
2980  }
2981 
2982  public function saveNewAccountMailObject(): void
2983  {
2984  $this->raiseErrorOnMissingWrite();
2985  $form = $this->initNewAccountMailForm();
2986 
2987  // If all forms in ILIAS use the UI/KS forms (here and in Services/Mail), we should move this to a proper constraint/trafo
2988  $is_valid_template_syntax = $this->dic->refinery()->custom()->constraint(function ($value): bool {
2989  try {
2990  $this->dic->mail()->mustacheFactory()->getBasicEngine()->render((string) $value, []);
2991  return true;
2992  } catch (Exception) {
2993  return false;
2994  }
2995  }, $this->dic->language()->txt('mail_template_invalid_tpl_syntax'));
2996 
2997  $valid_templates = true;
2998  $langs = $this->lng->getInstalledLanguages();
2999  foreach ($langs as $lang_key) {
3000  $subject = $this->user_request->getMailSubject($lang_key);
3001  try {
3002  $is_valid_template_syntax->check($subject);
3003  } catch (Exception) {
3004  $form->getItemByPostVar('subject_' . $lang_key)->setAlert(
3005  $is_valid_template_syntax->problemWith($subject)
3006  );
3007  $valid_templates = false;
3008  }
3009 
3010  $body = $this->user_request->getMailBody($lang_key);
3011  try {
3012  $is_valid_template_syntax->check($body);
3013  } catch (Exception) {
3014  $form->getItemByPostVar('body_' . $lang_key)->setAlert(
3015  $is_valid_template_syntax->problemWith($body)
3016  );
3017  $valid_templates = false;
3018  }
3019  }
3020  if (!$valid_templates) {
3021  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
3022  $this->newAccountMailObject($form);
3023  return;
3024  }
3025 
3026  foreach ($langs as $lang_key) {
3028  $lang_key,
3029  $this->user_request->getMailSubject($lang_key),
3030  $this->user_request->getMailSalutation('g', $lang_key),
3031  $this->user_request->getMailSalutation('f', $lang_key),
3032  $this->user_request->getMailSalutation('m', $lang_key),
3033  $this->user_request->getMailBody($lang_key)
3034  );
3035 
3036  if ($_FILES['att_' . $lang_key]['tmp_name']) {
3038  $lang_key,
3039  $_FILES['att_' . $lang_key]['tmp_name'],
3040  $_FILES['att_' . $lang_key]['name']
3041  );
3042  }
3043 
3044  if ($this->user_request->getMailAttDelete($lang_key)) {
3046  }
3047  }
3048 
3049  $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
3050  $this->ctrl->redirect(
3051  $this,
3052  'newAccountMail'
3053  );
3054  }
3055 
3056  public function getAdminTabs(): void
3057  {
3058  $this->getTabs();
3059  }
3060 
3061  protected function getTabs(): void
3062  {
3063  if ($this->access->checkRbacOrPositionPermissionAccess(
3064  'visible,read',
3066  $this->object->getRefId()
3067  )) {
3068  $this->tabs_gui->addTarget(
3069  'usrf',
3070  $this->ctrl->getLinkTarget(
3071  $this,
3072  'view'
3073  ),
3074  ['view', 'delete', 'resetFilter', 'userAction', ''],
3075  '',
3076  ''
3077  );
3078  }
3079 
3080  if ($this->access->checkRbacOrPositionPermissionAccess(
3081  'read',
3084  )) {
3085  $this->tabs_gui->addTarget(
3086  'search_user_extended',
3087  $this->ctrl->getLinkTargetByClass(
3088  'ilRepositorySearchGUI',
3089  ''
3090  ),
3091  [],
3092  'ilrepositorysearchgui',
3093  ''
3094  );
3095  }
3096 
3097  if ($this->rbac_system->checkAccess(
3098  'write',
3099  $this->object->getRefId()
3100  )) {
3101  $this->tabs_gui->addTarget(
3102  'settings',
3103  $this->ctrl->getLinkTarget(
3104  $this,
3105  'generalSettings'
3106  ),
3107  [
3108  'askForUserPasswordReset',
3109  'forceUserPasswordReset',
3110  'settings',
3111  'generalSettings',
3112  'listUserDefinedField',
3113  'newAccountMail'
3114  ]
3115  );
3116 
3117  $this->tabs_gui->addTarget(
3118  'export',
3119  $this->ctrl->getLinkTarget(
3120  $this,
3121  'export'
3122  ),
3123  'export',
3124  '',
3125  ''
3126  );
3127  }
3128 
3129  if ($this->rbac_system->checkAccess(
3130  'edit_permission',
3131  $this->object->getRefId()
3132  )) {
3133  $this->tabs_gui->addTarget(
3134  'perm_settings',
3135  $this->ctrl->getLinkTargetByClass(
3136  [get_class($this), 'ilpermissiongui'],
3137  'perm'
3138  ),
3139  ['perm', 'info', 'owner'],
3140  'ilpermissiongui'
3141  );
3142  }
3143  }
3144 
3145  public function setSubTabs(string $a_tab): void
3146  {
3147  switch ($a_tab) {
3148  case 'settings':
3149  $this->tabs_gui->addSubTabTarget(
3150  'general_settings',
3151  $this->ctrl->getLinkTarget(
3152  $this,
3153  'generalSettings'
3154  ),
3155  'generalSettings',
3156  get_class($this)
3157  );
3158  $this->tabs_gui->addSubTabTarget(
3159  'standard_fields',
3160  $this->ctrl->getLinkTarget(
3161  $this,
3162  'settings'
3163  ),
3164  ['settings', 'saveGlobalUserSettings'],
3165  get_class($this)
3166  );
3167  $this->tabs_gui->addSubTabTarget(
3168  'user_defined_fields',
3169  $this->ctrl->getLinkTargetByClass(
3170  'ilcustomuserfieldsgui',
3171  'listUserDefinedFields'
3172  ),
3173  'listUserDefinedFields',
3174  get_class($this)
3175  );
3176  $this->tabs_gui->addSubTabTarget(
3177  'user_new_account_mail',
3178  $this->ctrl->getLinkTarget(
3179  $this,
3180  'newAccountMail'
3181  ),
3182  'newAccountMail',
3183  get_class($this)
3184  );
3185 
3186  $this->tabs_gui->addSubTabTarget(
3187  'starting_points',
3188  $this->ctrl->getLinkTargetByClass(
3189  'iluserstartingpointgui',
3190  'startingPoints'
3191  ),
3192  'startingPoints',
3193  get_class($this)
3194  );
3195 
3196  $this->tabs_gui->addSubTabTarget(
3197  'user_profile_info',
3198  $this->ctrl->getLinkTargetByClass(
3199  SettingsGUI::class,
3200  ''
3201  ),
3202  '',
3203  SettingsGUI::class
3204  );
3205 
3206  break;
3207  }
3208  }
3209 
3210  public static function _goto(string $a_user): void
3211  {
3212  global $DIC;
3213 
3214  $a_user = (int) $a_user;
3215  $main_tpl = $DIC->ui()->mainTemplate();
3216 
3217  $ilAccess = $DIC['ilAccess'];
3218  $ilErr = $DIC['ilErr'];
3219  $lng = $DIC['lng'];
3220  $ctrl = $DIC['ilCtrl'];
3221 
3222  $a_target = USER_FOLDER_ID;
3223 
3224  if ($ilAccess->checkAccess(
3225  'read',
3226  '',
3227  $a_target
3228  )) {
3229  $ctrl->redirectToURL('ilias.php?baseClass=ilAdministrationGUI&ref_id=' . $a_target . '&jmpToUser=' . $a_user);
3230  exit;
3231  } else {
3232  if ($ilAccess->checkAccess(
3233  'read',
3234  '',
3236  )) {
3237  $main_tpl->setOnScreenMessage('failure', sprintf(
3238  $lng->txt('msg_no_perm_read_item'),
3240  ), true);
3242  }
3243  }
3244  $ilErr->raiseError(
3245  $lng->txt('msg_no_perm_read'),
3246  $ilErr->FATAL
3247  );
3248  }
3249 
3253  public function jumpToUserObject(): void
3254  {
3255  $jump_to_user = $this->user_request->getJumpToUser();
3256  if (ilObject::_lookupType($jump_to_user) == 'usr') {
3257  $this->ctrl->setParameterByClass(
3258  'ilobjusergui',
3259  'obj_id',
3260  $jump_to_user
3261  );
3262  $this->ctrl->redirectByClass(
3263  'ilobjusergui',
3264  'view'
3265  );
3266  }
3267  }
3268 
3269  public function searchUserAccessFilterCallable(array $a_user_ids): array // Missing array type.
3270  {
3271  if (!$this->checkPermissionBool('read_users')) {
3272  $a_user_ids = $this->access->filterUserIdsByPositionOfCurrentUser(
3275  $a_user_ids
3276  );
3277  }
3278 
3279  return $a_user_ids;
3280  }
3281 
3285  public function searchResultHandler(
3286  array $a_usr_ids,
3287  string $a_cmd
3288  ): bool {
3289  if (!count($a_usr_ids)) {
3290  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
3291  return false;
3292  }
3293 
3294  $this->requested_ids = $a_usr_ids;
3295 
3296  // no real confirmation here
3297  if (stripos($a_cmd, 'export') !== false) {
3298  $cmd = $a_cmd . 'Object';
3299  return $this->$cmd();
3300  }
3301 
3302  return $this->showActionConfirmation(
3303  $a_cmd,
3304  true
3305  );
3306  }
3307 
3308  public function getUserMultiCommands(bool $a_search_form = false): array // Missing array type.
3309  {
3310  $cmds = [];
3311  // see searchResultHandler()
3312  if ($a_search_form) {
3313  if ($this->rbac_system->checkAccess('write', $this->object->getRefId())) {
3314  $cmds = [
3315  'activate' => $this->lng->txt('activate'),
3316  'deactivate' => $this->lng->txt('deactivate'),
3317  'accessRestrict' => $this->lng->txt('accessRestrict'),
3318  'accessFree' => $this->lng->txt('accessFree')
3319  ];
3320  }
3321 
3322  if ($this->rbac_system->checkAccess('delete', $this->object->getRefId())) {
3323  $cmds['delete'] = $this->lng->txt('delete');
3324  }
3325  } else {
3326  if ($this->rbac_system->checkAccess('write', $this->object->getRefId())) {
3327  $cmds = [
3328  'activateUsers' => $this->lng->txt('activate'),
3329  'deactivateUsers' => $this->lng->txt('deactivate'),
3330  'restrictAccess' => $this->lng->txt('accessRestrict'),
3331  'freeAccess' => $this->lng->txt('accessFree')
3332  ];
3333  }
3334 
3335  if ($this->rbac_system->checkAccess('delete', $this->object->getRefId())) {
3336  $cmds['deleteUsers'] = $this->lng->txt('delete');
3337  }
3338  }
3339 
3340  if ($this->rbac_system->checkAccess('write', $this->object->getRefId())) {
3341  $export_types = [
3342  'userfolder_export_excel_x86',
3343  'userfolder_export_csv',
3344  'userfolder_export_xml'
3345  ];
3346  foreach ($export_types as $type) {
3347  $cmd = explode(
3348  '_',
3349  $type
3350  );
3351  $cmd = array_pop($cmd);
3352  $cmds['usrExport' . ucfirst($cmd)] = $this->lng->txt('export') . ' - ' .
3353  $this->lng->txt($type);
3354  }
3355  }
3356 
3357  // check if current user may send mails
3358  $mail = new ilMail($this->user->getId());
3359  if ($this->rbac_system->checkAccess(
3360  'internal_mail',
3361  $mail->getMailObjectReferenceId()
3362  )) {
3363  $cmds['mail'] = $this->lng->txt('send_mail');
3364  }
3365 
3366  $cmds['addToClipboard'] = $this->lng->txt('clipboard_add_btn');
3367 
3368  return $cmds;
3369  }
3370 
3371  protected function usrExportX86Object(): void
3372  {
3373  $user_ids = $this->getActionUserIds();
3374  if (!$user_ids) {
3375  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
3376  $this->ctrl->redirect(
3377  $this,
3378  'view'
3379  );
3380  }
3381 
3382  if ($this->checkPermissionBool('write,read_users')) {
3383  $this->object->buildExportFile(
3385  $user_ids
3386  );
3387  $this->ctrl->redirectByClass(
3388  'ilobjuserfoldergui',
3389  'export'
3390  );
3391  } elseif ($this->checkUserManipulationAccessBool()) {
3392  $fullname = $this->object->buildExportFile(
3394  $user_ids,
3395  true
3396  );
3398  $fullname . '.xlsx',
3399  $this->object->getExportFilename(ilObjUserFolder::FILE_TYPE_EXCEL) . '.xlsx',
3400  '',
3401  false,
3402  true
3403  );
3404  }
3405  }
3406 
3407  protected function usrExportCsvObject(): void
3408  {
3409  $user_ids = $this->getActionUserIds();
3410  if (!$user_ids) {
3411  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
3412  $this->ctrl->redirect(
3413  $this,
3414  'view'
3415  );
3416  }
3417 
3418  if ($this->checkPermissionBool('write,read_users')) {
3419  $this->object->buildExportFile(
3421  $user_ids
3422  );
3423  $this->ctrl->redirectByClass(
3424  'ilobjuserfoldergui',
3425  'export'
3426  );
3427  } elseif ($this->checkUserManipulationAccessBool()) {
3428  $fullname = $this->object->buildExportFile(
3430  $user_ids,
3431  true
3432  );
3434  $fullname,
3435  $this->object->getExportFilename(ilObjUserFolder::FILE_TYPE_CSV),
3436  '',
3437  false,
3438  true
3439  );
3440  }
3441  }
3442 
3443  protected function usrExportXmlObject(): void
3444  {
3445  $user_ids = $this->getActionUserIds();
3446  if (!$user_ids) {
3447  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
3448  $this->ctrl->redirect(
3449  $this,
3450  'view'
3451  );
3452  }
3453  if ($this->checkPermissionBool('write,read_users')) {
3454  $this->object->buildExportFile(
3456  $user_ids
3457  );
3458  $this->ctrl->redirectByClass(
3459  'ilobjuserfoldergui',
3460  'export'
3461  );
3462  } elseif ($this->checkUserManipulationAccessBool()) {
3463  $fullname = $this->object->buildExportFile(
3465  $user_ids,
3466  true
3467  );
3469  $fullname,
3470  $this->object->getExportFilename(ilObjUserFolder::FILE_TYPE_XML),
3471  '',
3472  false,
3473  true
3474  );
3475  }
3476  }
3477 
3478  protected function mailObject(): void
3479  {
3480  $user_ids = $this->getActionUserIds();
3481  if (!$user_ids) {
3482  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
3483  $this->ctrl->redirect(
3484  $this,
3485  'view'
3486  );
3487  return;
3488  }
3489 
3490  // remove existing (temporary) lists
3491  $old_lists = new ilMailingLists($this->user);
3492  $old_lists->deleteTemporaryLists();
3493 
3494  // create (temporary) mailing list
3495  $list = new ilMailingList($this->user);
3496  $list->setMode(ilMailingList::MODE_TEMPORARY);
3497  $list->setTitle('-TEMPORARY SYSTEM LIST-');
3498  $list->setDescription('-USER ACCOUNTS MAIL-');
3499  $list->setCreatedate(date('Y-m-d H:i:s'));
3500  $list->insert();
3501  $list_id = $list->getId();
3502 
3503  // after list has been saved...
3504  foreach ($user_ids as $user_id) {
3505  $list->assignUser((int) $user_id);
3506  }
3507 
3508  $umail = new ilFormatMail($this->user->getId());
3509  $mail_data = $umail->retrieveFromStage();
3510 
3511  $umail->persistToStage(
3512  $mail_data['user_id'],
3513  $mail_data['attachments'],
3514  '#il_ml_' . $list_id,
3515  $mail_data['rcp_cc'],
3516  $mail_data['rcp_bcc'],
3517  $mail_data['m_subject'],
3518  $mail_data['m_message'],
3519  $mail_data['use_placeholders'],
3520  $mail_data['tpl_ctx_id'],
3521  $mail_data['tpl_ctx_params']
3522  );
3523 
3524  $this->ctrl->redirectToURL(
3526  $this,
3527  '',
3528  [],
3529  ['type' => 'search_res']
3530  )
3531  );
3532  }
3533 
3534  public function addToExternalSettingsForm(int $a_form_id): array // Missing array type.
3535  {
3536  switch ($a_form_id) {
3538  $security = ilSecuritySettings::_getInstance();
3539 
3540  $fields = [];
3541 
3542  $subitems = [
3543  'ps_password_change_on_first_login_enabled' => [
3544  $security->isPasswordChangeOnFirstLoginEnabled(),
3546  ],
3547  'ps_password_must_not_contain_loginame' => [
3548  $security->getPasswordMustNotContainLoginnameStatus(),
3550  ],
3551  'ps_password_chars_and_numbers_enabled' => [
3552  $security->isPasswordCharsAndNumbersEnabled(),
3554  ],
3555  'ps_password_special_chars_enabled' => [
3556  $security->isPasswordSpecialCharsEnabled(),
3558  ],
3559  'ps_password_min_length' => $security->getPasswordMinLength(),
3560  'ps_password_max_length' => $security->getPasswordMaxLength(),
3561  'ps_password_uppercase_chars_num' => $security->getPasswordNumberOfUppercaseChars(),
3562  'ps_password_lowercase_chars_num' => $security->getPasswordNumberOfLowercaseChars(),
3563  'ps_password_max_age' => $security->getPasswordMaxAge()
3564  ];
3565  $fields['ps_password_settings'] = [null, null, $subitems];
3566 
3567  $subitems = [
3568  'ps_login_max_attempts' => $security->getLoginMaxAttempts(),
3569  'ps_prevent_simultaneous_logins' => [
3570  $security->isPreventionOfSimultaneousLoginsEnabled(),
3572  ]
3573  ];
3574  $fields['ps_security_protection'] = [null, null, $subitems];
3575 
3576  return [['generalSettings', $fields]];
3577  }
3578  return [];
3579  }
3580 
3581  private function redirectAfterImport(): void
3582  {
3583  if ($this->inAdministration()) {
3584  $this->ctrl->redirect(
3585  $this,
3586  'view'
3587  );
3588  }
3589 
3590  $this->ctrl->redirectByClass(
3591  'ilobjcategorygui',
3592  'listUsers'
3593  );
3594  }
3595 
3596  protected function addToClipboardObject(): void
3597  {
3598  $users = $this->getActionUserIds();
3599  if (!count($users)) {
3600  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
3601  $this->ctrl->redirect(
3602  $this,
3603  'view'
3604  );
3605  }
3606  $clip = ilUserClipboard::getInstance($GLOBALS['DIC']['ilUser']->getId());
3607  $clip->add($users);
3608  $clip->save();
3609 
3610  $this->tpl->setOnScreenMessage('success', $this->lng->txt('clipboard_user_added'), true);
3611  $this->ctrl->redirect(
3612  $this,
3613  'view'
3614  );
3615  }
3616 
3617  private function checkbox(string $name): ilCheckboxInputGUI
3618  {
3619  $checkbox = new ilCheckboxInputGUI($this->lng->txt($name), $name);
3620  $checkbox->setInfo($this->lng->txt($name . '_desc'));
3621  $checkbox->setValue('1');
3622 
3623  return $checkbox;
3624  }
3625 
3626  private function raiseErrorOnMissingWrite(): void
3627  {
3628  if (!$this->access->checkRbacOrPositionPermissionAccess(
3629  'write',
3632  )) {
3633  $this->ilias->raiseError(
3634  $this->lng->txt('permission_denied'),
3635  $this->ilias->error_obj->MESSAGE
3636  );
3637  }
3638  }
3639 }
static _getAllUserIds(int $a_filter=0)
showFieldChangeComponentsListeningConfirmDialog(array $interested_change_listeners)
static get(string $a_var)
Global event handler.
searchUserAccessFilterCallable(array $a_user_ids)
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ilObjUser $user=null,)
static _writeNewAccountMail(string $a_lang, string $a_subject, string $a_sal_g, string $a_sal_f, string $a_sal_m, string $a_body)
importUsersObject()
Import Users with new form implementation.
__buildUserFilterSelect()
build select form to distinguish between active and non-active users
static _saveStatus(string $a_key, bool $a_enabled)
const IL_CAL_DATETIME
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
static getLogger(string $a_component_id)
Get component logger.
const USER_FOLDER_ID
Definition: constants.php:33
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getItemByPostVar(string $a_post_var)
const ROOT_FOLDER_ID
Definition: constants.php:32
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
static _isSearchable(string $a_key)
Singleton class that stores all security settings.
prepareOutput(bool $show_sub_objects=true)
This class represents a file property in a property form.
Interface Observer Contains several chained tasks and infos about them.
const SYSTEM_ROLE_ID
Definition: constants.php:29
importUserRoleAssignmentObject()
display form for user import with new FileSystem implementation
$valid
Class ilUserProfile.
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
isPasswordCharsAndNumbersEnabled()
get boolean if the passwords have to contain characters and numbers
settingsObject()
Global user settings Allows to define global settings for user accounts Note: The Global user setting...
static formSelect( $selected, string $varname, array $options, bool $multiple=false, bool $direct_text=false, int $size=0, string $style_class="", array $attribs=[], bool $disabled=false)
Builds a select form field with options and shows the selected option first.
setShowTime(bool $a_showtime)
getFullname(int $a_max_strlen=0)
getUserMultiCommands(bool $a_search_form=false)
getPasswordPolicySettingsMap(\ilSecuritySettings $security)
setSuffixes(array $a_suffixes)
static _updateAccountMailAttachment(string $a_lang, string $a_tmp_name, string $a_name)
Update account mail attachment.
setVariable(string $variable, $value='')
Sets the given variable to the given value.
Class ilRoleMailboxSearch.
filterUserIdsByRbacOrPositionOfCurrentUser(array $user_ids)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const IL_CAL_UNIX
static _reset()
Reset all.
showActionConfirmation(string $action, bool $a_from_search=false)
$ilErr
Definition: raiseError.php:17
$path
Definition: ltiservices.php:30
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a date/time property in a property form.
static _lookupObjId(int $ref_id)
getPasswordMaxLength()
get the maximum length for passwords
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
newAccountMailObject(ilPropertyFormGUI $form=null)
retrieveFromStage()
getActionUserIds()
Get selected items for table action.
final const MODE_TEMPORARY
ilLanguage $lng
getPasswordNumberOfLowercaseChars()
Returns number of lowercase characters required.
TableGUI class for user administration.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilMailRfc822AddressParserFactory.
initUserRoleAssignmentForm(string $xml_file_full_path)
Class ilCustomUserFieldsGUI.
getPasswordNumberOfUppercaseChars()
Returns number of uppercase characters required.
static _goto(string $a_user)
ilGlobalTemplateInterface $tpl
static _lookupTitle(int $obj_id)
saveGeneralSettingsObject()
Save user account settings.
static _lookupNewAccountMail(string $a_lang)
$GLOBALS["DIC"]
Definition: wac.php:30
searchResultHandler(array $a_usr_ids, string $a_cmd)
Handles multi command from repository search gui.
setFormAction(string $a_formaction)
static _getUserFolderId()
Class ilUserStartingPointGUI.
setVisible(string $field, bool $visible)
Set a profile field being visible.
saveGlobalUserSettingsObject(string $action='')
getTranslationForField(string $field_name, array $properties)
isPasswordSpecialCharsEnabled()
get boolean if the passwords have to contain special characters
$text
Definition: xapiexit.php:21
getPasswordMinLength()
get the minimum length for passwords
Class ilObjectGUI Basic methods of all Output classes.
global $DIC
Definition: shib_login.php:25
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
Class ilObjForumAdministration.
static _deleteAccountMailAttachment(string $a_lang)
Delete account mail attachment.
Class FileUpload.
Definition: FileUpload.php:34
static getDataDir()
get data directory (outside webspace)
addToExternalSettingsForm(int $a_form_id)
setRequired(bool $a_required)
setTitleIcon(string $a_titleicon)
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Group.php:59
jumpToUserObject()
Jump to edit screen for user.
addCommandButton(string $a_cmd, string $a_text, string $a_id="")
const ROLE_FOLDER_ID
Definition: constants.php:34
setChangeable(string $field, bool $changeable)
Set a profile field being changeable.
setAllowDeletion(bool $a_val)
checkPermissionBool(string $perm, string $cmd="", string $type="", ?int $ref_id=null)
downloadExportFileObject()
Download selected export files Sends a selected export file for download.
showPossibleSubObjects()
show possible subobjects (pulldown menu) overwritten to prevent displaying of role templates in local...
setCurrentBlock(string $part=self::DEFAULT_BLOCK)
Sets the template to the given block.
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
getProtocolAsHTML(string $a_log_title)
Returns the protocol as a HTML table.
getErrorLevel()
Returns the error level.
const ANONYMOUS_ROLE_ID
Definition: constants.php:28
form( $class_path, string $cmd, string $submit_caption="")
__construct(Container $dic, ilPlugin $plugin)
This class represents a text area property in a property form.
static getRedirectTarget( $gui, string $cmd, array $gui_params=[], array $mail_params=[], array $context_params=[])
verifyXmlData(ilUserImportParser $import_parser)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$check
Definition: buildRTE.php:81
__construct( $a_data, int $a_id, bool $a_call_by_reference)
const ilPropertyFormGUI $form
redirectToURL(string $target_url)
initAccessRestrictionForm(bool $a_from_search=false)
parseCurrentBlock(string $block_name=self::DEFAULT_BLOCK)
Parses the given block.
static _getAssignUsersStatus(int $a_role_id)
static _lookupType(int $id, bool $reference=false)
$post
Definition: ltitoken.php:46
static _getInstance()
Get instance of ilSecuritySettings.
ilSetting $settings
checkPermission(string $perm, string $cmd="", string $type="", ?int $ref_id=null)
getPasswordMustNotContainLoginnameStatus()
Return whether the password must not contain the loginname or not.
static getInstance(int $a_usr_id)
redirectOnRoleWithMissingWrite(int $role_id, array $roles_of_user, array $global_roles, string $import_dir)
setAccessRestrictionObject(?ilPropertyFormGUI $a_form=null, bool $a_from_search=false)
static _gotoRepositoryRoot(bool $raise_error=false)
Goto repository root.
ilUserSettingsConfig $user_settings_config