ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilContactGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
23 use ILIAS\Data\URI;
27 
35 {
36  final public const string CONTACTS_VIEW_GALLERY = 'buddy_view_gallery';
37  final public const string CONTACTS_VIEW_TABLE = 'buddy_view_table';
38 
39  private readonly \ILIAS\HTTP\GlobalHttpState $http;
42  protected ilLanguage $lng;
43  protected ilTabsGUI $tabs_gui;
44  protected ilHelpGUI $help;
46  protected ilFormatMail $umail;
47  protected ilObjUser $user;
50  protected bool $has_sub_tabs = false;
51  protected Refinery $refinery;
52  protected \ILIAS\UI\Factory $ui_factory;
53  protected \ILIAS\UI\Renderer $ui_renderer;
54  private readonly RelationsTable $relations_table;
56  private array $view_mode_options = [
57  self::CONTACTS_VIEW_TABLE => self::CONTACTS_VIEW_TABLE,
58  self::CONTACTS_VIEW_GALLERY => self::CONTACTS_VIEW_GALLERY,
59  ];
60 
61  public function __construct(
62  string $format_mail_class = ilFormatMail::class,
63  string $relations_table_class = RelationsTable::class
64  ) {
65  global $DIC;
66 
67  $this->tpl = $DIC['tpl'];
68  $this->ctrl = $DIC['ilCtrl'];
69  $this->lng = $DIC['lng'];
70  $this->tabs_gui = $DIC['ilTabs'];
71  $this->help = $DIC['ilHelp'];
72  $this->toolbar = $DIC['ilToolbar'];
73  $this->user = $DIC['ilUser'];
74  $this->error = $DIC['ilErr'];
75  $this->rbacsystem = $DIC['rbacsystem'];
76  $this->http = $DIC->http();
77  $this->refinery = $DIC->refinery();
78  $this->ui_factory = $DIC->ui()->factory();
79  $this->ui_renderer = $DIC->ui()->renderer();
80 
81  $this->ctrl->saveParameter($this, "mobj_id");
82 
83  $this->umail = new $format_mail_class($this->user->getId());
84  $this->relations_table = new $relations_table_class(
85  $this->ui_factory,
86  $this->lng,
87  $DIC->uiService(),
89  );
90  $this->lng->loadLanguageModule('buddysystem');
91  }
92 
93  public function executeCommand(): bool
94  {
95  $this->showSubTabs();
96 
97  $forward_class = $this->ctrl->getNextClass($this) ?? '';
98 
99  $this->umail->persistToStage($this->user->getId(), [], '', '', '', '', '', false);
100 
101  switch (strtolower($forward_class)) {
102  case strtolower(ilMailSearchCoursesGUI::class):
103  $this->activateTab('mail_my_courses');
104 
105  $this->ctrl->setReturn($this, "showContacts");
106  $this->ctrl->forwardCommand(new ilMailSearchCoursesGUI());
107  break;
108 
109  case strtolower(ilMailSearchGroupsGUI::class):
110  $this->activateTab('mail_my_groups');
111 
112  $this->ctrl->setReturn($this, "showContacts");
113  $this->ctrl->forwardCommand(new ilMailSearchGroupsGUI());
114  break;
115 
116  case strtolower(ilMailingListsGUI::class):
117  $this->activateTab('mail_my_mailing_lists');
118 
119  $this->ctrl->setReturn($this, "showContacts");
120  $this->ctrl->forwardCommand(new ilMailingListsGUI());
121  break;
122 
123  case strtolower(ilUsersGalleryGUI::class):
124  if (!ilBuddySystem::getInstance()->isEnabled()) {
125  $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->MESSAGE);
126  }
127 
128  $this->tabs_gui->activateSubTab('buddy_view_gallery');
129  $this->activateTab('my_contacts');
130  $this->ctrl->forwardCommand(new ilUsersGalleryGUI(new ilUsersGalleryContacts()));
131  $this->tpl->printToStdout();
132  break;
133 
134  case strtolower(ilPublicUserProfileGUI::class):
135  $profile_gui = new ilPublicUserProfileGUI(
136  $this->http->wrapper()->query()->retrieve('user', $this->refinery->kindlyTo()->int())
137  );
138  $profile_gui->setBackUrl($this->ctrl->getLinkTarget($this, 'showContacts'));
139  $this->ctrl->forwardCommand($profile_gui);
140  $this->tpl->printToStdout();
141  break;
142 
143  default:
144  $this->activateTab('mail_my_entries');
145 
146  if (!($cmd = $this->ctrl->getCmd())) {
147  if (ilBuddySystem::getInstance()->isEnabled()) {
148  $cmd = 'showContacts';
149  } else {
150  $this->ctrl->redirectByClass(ilMailSearchCoursesGUI::class);
151  }
152  }
153 
154  $this->$cmd();
155  break;
156  }
157  return true;
158  }
159 
160 
161  private function showSubTabs(): void
162  {
163  $galleryCmdClasses = array_map('strtolower', [ilUsersGalleryGUI::class, self::class]);
164  if ($this->tabs_gui->hasTabs()) {
165  if (ilBuddySystem::getInstance()->isEnabled()) {
166  $this->tabs_gui->addSubTab(
167  'my_contacts',
168  $this->lng->txt('my_contacts'),
169  $this->ctrl->getLinkTarget($this)
170  );
171 
172  if (in_array(strtolower($this->ctrl->getCmdClass() ?? ''), $galleryCmdClasses, true)) {
173  $mode_options = array_combine(
174  array_map(
175  fn(string $mode): string => $this->lng->txt($mode),
176  array_keys($this->view_mode_options)
177  ),
178  array_map(
179  function (string $mode): string {
180  $this->ctrl->setParameter($this, 'contacts_view', $mode);
181  $url = $this->ctrl->getFormAction($this, 'changeContactsView');
182  $this->ctrl->setParameter($this, 'contacts_view', null);
183 
184  return $url;
185  },
186  array_keys($this->view_mode_options)
187  ),
188  );
189 
190  $active_mode = strtolower($this->ctrl->getCmdClass() ?? '') === strtolower(ilUsersGalleryGUI::class)
191  ? self::CONTACTS_VIEW_GALLERY
192  : self::CONTACTS_VIEW_TABLE;
193 
194  $sortViewControl = $this->ui_factory
195  ->viewControl()
196  ->mode($mode_options, $this->lng->txt($active_mode))
197  ->withActive($this->lng->txt($active_mode));
198  $this->toolbar->addComponent($sortViewControl);
199  }
200 
201  if (
202  count(ilBuddyList::getInstanceByGlobalUser()->getLinkedRelations()) > 0 ||
203  (new ilMailingLists($this->user))->hasAny()
204  ) {
205  $this->tabs_gui->addSubTab(
206  'mail_my_mailing_lists',
207  $this->lng->txt('mail_my_mailing_lists'),
208  $this->ctrl->getLinkTargetByClass(ilMailingListsGUI::class)
209  );
210  }
211  }
212 
213  $this->tabs_gui->addSubTab(
214  'mail_my_courses',
215  $this->lng->txt('mail_my_courses'),
216  $this->ctrl->getLinkTargetByClass(ilMailSearchCoursesGUI::class)
217  );
218  $this->tabs_gui->addSubTab(
219  'mail_my_groups',
220  $this->lng->txt('mail_my_groups'),
221  $this->ctrl->getLinkTargetByClass(ilMailSearchGroupsGUI::class)
222  );
223  $this->has_sub_tabs = true;
224  } else {
225  $this->tpl->setTitleIcon(ilUtil::getImagePath('standard/icon_cadm.svg'));
226 
227  $this->help->setScreenIdComponent('contacts');
228 
229  if (ilBuddySystem::getInstance()->isEnabled()) {
230  $this->tabs_gui->addTab(
231  'my_contacts',
232  $this->lng->txt('my_contacts'),
233  $this->ctrl->getLinkTarget($this)
234  );
235 
236  if (in_array(strtolower($this->ctrl->getCmdClass() ?? ''), $galleryCmdClasses, true)) {
237  $this->tabs_gui->addSubTab(
238  'buddy_view_table',
239  $this->lng->txt('buddy_view_table'),
240  $this->ctrl->getLinkTarget($this)
241  );
242  $this->tabs_gui->addSubTab(
243  'buddy_view_gallery',
244  $this->lng->txt('buddy_view_gallery'),
245  $this->ctrl->getLinkTargetByClass(ilUsersGalleryGUI::class)
246  );
247  }
248 
249  if (
250  count(ilBuddyList::getInstanceByGlobalUser()->getLinkedRelations()) > 0 ||
251  (new ilMailingLists($this->user))->hasAny()
252  ) {
253  $this->tabs_gui->addTab(
254  'mail_my_mailing_lists',
255  $this->lng->txt('mail_my_mailing_lists'),
256  $this->ctrl->getLinkTargetByClass(ilMailingListsGUI::class)
257  );
258  }
259  }
260 
261  $this->tabs_gui->addTab(
262  'mail_my_courses',
263  $this->lng->txt('mail_my_courses'),
264  $this->ctrl->getLinkTargetByClass(ilMailSearchCoursesGUI::class)
265  );
266  $this->tabs_gui->addTab(
267  'mail_my_groups',
268  $this->lng->txt('mail_my_groups'),
269  $this->ctrl->getLinkTargetByClass(ilMailSearchGroupsGUI::class)
270  );
271  }
272  }
273 
274  protected function activateTab(string $a_id): void
275  {
276  if ($this->has_sub_tabs) {
277  $this->tabs_gui->activateSubTab($a_id);
278  } else {
279  $this->tabs_gui->activateTab($a_id);
280  }
281  }
282 
286  protected function changeContactsView(): void
287  {
288  if (!ilBuddySystem::getInstance()->isEnabled()) {
289  $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->MESSAGE);
290  }
291 
292  $contacts_view = $this->http->wrapper()->query()->retrieve(
293  'contacts_view',
294  $this->refinery->byTrying([
295  $this->refinery->kindlyTo()->string(),
296  $this->refinery->always(self::CONTACTS_VIEW_TABLE)
297  ])
298  );
299 
300  switch ($contacts_view) {
301  case self::CONTACTS_VIEW_GALLERY:
302  $this->ctrl->redirectByClass(ilUsersGalleryGUI::class);
303 
304  // no break
305  case self::CONTACTS_VIEW_TABLE:
306  default:
307  $this->ctrl->redirect($this);
308  }
309  }
310 
311  protected function showContacts(): void
312  {
313  if (!ilBuddySystem::getInstance()->isEnabled()) {
314  $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->MESSAGE);
315  }
316 
317  $this->tabs_gui->activateSubTab('buddy_view_table');
318  $this->activateTab('my_contacts');
319 
320  $content = $this->chatroomInvitationMessage();
321  $action = $this->contactAction();
322  $chat_allowed = (bool) (new ilSetting('chatroom'))->get('chat_enabled', '0');
323  $mail_allowed = $this->rbacsystem->checkAccess(
324  'internal_mail',
326  );
327 
328  $content = array_merge($content, $this->relations_table->build(array_merge(
329  $chat_allowed ? ['chat' => $action('standard', 'invite_to_chat', 'inviteToChat')] : [],
330  $mail_allowed ? ['mail' => $action('standard', 'send_mail', 'mailToUsers')] : [],
331  ), $this->ctrl->getLinkTarget($this, 'showContacts'), $action));
332 
333  $this->tpl->setContent($this->ui_renderer->render($content));
334  $this->tpl->printToStdout();
335  }
336 
337  private function updateState(): void
338  {
339  $get = $this->http->wrapper()->query()->retrieve(...);
340 
341  $user_ids = $get('contact_user_ids', $this->refinery->byTrying([
342  $this->refinery->null(),
343  $this->refinery->kindlyTo()->listOf($this->refinery->byTrying([
344  $this->refinery->kindlyTo()->int(),
345  ])),
346  $this->refinery->custom()->transformation(
347  fn($s): array => is_array($s) && join('', $s) === 'ALL_OBJECTS' ?
348  array_column(RelationsTable::data(), 'user_id') :
349  throw new Exception('Nope')
350  ),
351  ]));
352 
353  $action = $get('contact_action', $this->refinery->kindlyTo()->string());
354  if (!$user_ids) {
355  $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_one'), true);
356  $this->ctrl->redirect($this);
357  }
358 
359  if (in_array($action, ['inviteToChat', 'mailToUsers'], true)) {
360  $this->$action($user_ids);
361  return;
362  }
363 
364  $this->updateRelationState(current($user_ids), $action);
365  }
366 
367  private function updateRelationState(int $user, string $action): void
368  {
369  $login = ilObjUser::_lookupLogin($user);
370  if (ilObjUser::_isAnonymous($user)) {
371  throw new ilBuddySystemException('You cannot perform a state transition for the anonymous user');
372  }
373  if (!$login) {
374  throw new ilBuddySystemException(sprintf(
375  'You cannot perform a state transition for a non existing user (id: %s)',
376  $user
377  ));
378  }
380  $relation = $list->getRelationByUserId($user);
381  if (
382  $relation->isUnlinked() &&
383  !ilUtil::yn2tf((string) ilObjUser::_lookupPref($relation->getBuddyUsrId(), 'bs_allow_to_contact_me'))
384  ) {
385  throw new ilException('The requested user does not want to get contact requests');
386  }
387 
388  try {
389  $list->$action($relation);
391  $this->tpl->setOnScreenMessage('failure', sprintf($this->lng->txt($e->getMessage()), $login), true);
392  } catch (Exception) {
393  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('buddy_bs_action_not_possible'), true);
394  }
395 
396  $this->ctrl->redirect($this, 'showContacts');
397  }
398 
402  protected function mailToUsers(array $usr_ids): void
403  {
404  if (!$this->rbacsystem->checkAccess('internal_mail', ilMailGlobalServices::getMailObjectRefId())) {
405  $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->MESSAGE);
406  }
407 
408  $logins = [];
409  $mail_data = $this->umail->retrieveFromStage();
410  foreach ($usr_ids as $usr_id) {
411  $login = ilObjUser::_lookupLogin($usr_id);
412  if (!$this->umail->existsRecipient($login, (string) $mail_data['rcp_to'])) {
413  $logins[] = $login;
414  }
415  }
416  $logins = array_filter($logins);
417 
418  if ($logins !== []) {
419  $mail_data = $this->umail->appendSearchResult($logins, 'to');
420  $this->umail->persistToStage(
421  (int) $mail_data['user_id'],
422  $mail_data['attachments'],
423  $mail_data['rcp_to'],
424  $mail_data['rcp_cc'],
425  $mail_data['rcp_bcc'],
426  $mail_data['m_subject'],
427  $mail_data['m_message'],
428  $mail_data['use_placeholders'],
429  $mail_data['tpl_ctx_id'],
430  $mail_data['tpl_ctx_params']
431  );
432  }
433 
434  $this->ctrl->redirectToURL('ilias.php?baseClass=ilMailGUI&type=search_res');
435  }
436 
437  public function submitInvitation(): void
438  {
439  try {
440  $usr_ids = $this->http->wrapper()->post()->retrieve('usr_ids', $this->refinery->in()->series([
441  $this->refinery->kindlyTo()->string(),
442  $this->refinery->custom()->transformation(fn(string $s) => explode(',', $s)),
443  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
444  $this->refinery->custom()->constraint(fn(array $a) => $a !== [], fn() => 'Empty array.'),
445  ]));
446  } catch (Exception) {
447  $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_one'), true);
448  $this->ctrl->redirect($this);
449  }
450 
451  try {
452  $room_id = $this->http->wrapper()->post()->retrieve('room_id', $this->refinery->kindlyTo()->int());
453  } catch (Exception) {
454  $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_one'));
455  $this->inviteToChat($usr_ids);
456  return;
457  }
458 
459  $room = ilChatroom::byRoomId($room_id, true);
460 
461  $no_access = [];
462  $no_login = [];
463  $valid_users = [];
464  $ref_id = $room->getRefIdByRoomId($room_id);
465 
466  foreach ($usr_ids as $usr_id) {
467  $login = ilObjUser::_lookupLogin($usr_id);
468  if ($login === '') {
469  $no_login[] = $usr_id;
470  } elseif (
471  !ilChatroom::checkPermissionsOfUser($usr_id, 'read', $ref_id) ||
472  $room->isUserBanned($usr_id)
473  ) {
474  $no_access[] = $login;
475  } else {
476  $valid_users[] = $usr_id;
477  }
478  }
479 
480  $message = join('', [
481  $this->asErrorMessage($no_access, $this->lng->txt('chat_users_without_permission')),
482  $this->asErrorMessage($no_login, $this->lng->txt('chat_users_without_login')),
483  ]);
484 
485  if ($message !== '') {
486  $this->tpl->setOnScreenMessage('failure', $message);
487  $this->inviteToChat($usr_ids);
488  return;
489  }
490 
491  foreach ($valid_users as $id) {
492  $room->sendInvitationNotification(
493  null,
494  $this->user->getId(),
495  $id,
497  );
498  }
499 
500  $this->ctrl->setParameter($this, 'inv_room_ref_id', $ref_id);
501  $this->ctrl->setParameter($this, 'inv_usr_ids', implode(',', $valid_users));
502 
503  $this->ctrl->redirect($this);
504  }
505 
509  protected function inviteToChat(array $usr_ids): void
510  {
511  $this->tabs_gui->activateSubTab('buddy_view_table');
512  $this->activateTab('my_contacts');
513 
514  $this->lng->loadLanguageModule('chatroom');
515 
516  $chat_rooms = (new ilChatroom())->getAccessibleRoomIdByTitleMap($this->user->getId());
517 
518  $options = array_filter(
519  $chat_rooms,
520  fn(int $room_id) => !(ilChatroom::byRoomId($room_id))->isUserBanned($this->user->getId()),
521  ARRAY_FILTER_USE_KEY
522  );
523 
524  asort($options);
525 
526  $this->tpl->setTitle($this->lng->txt('mail_invite_users_to_chat'));
527  $this->tpl->setContent($this->inviteToChatForm($options, $usr_ids)->getHTML());
528  $this->tpl->printToStdout();
529  }
530 
534  private function asErrorMessage(array $array, string $title): string
535  {
536  if ($array === []) {
537  return '';
538  }
539 
540  $items = array_map(
541  fn($s) => '<li>' . htmlspecialchars((string) $s) . '</li>',
542  $array
543  );
544 
545  return sprintf(
546  '%s<br><ul>%s</ul>',
547  $title,
548  join('', $items)
549  );
550  }
551 
556  private function inviteToChatForm(array $options, array $usr_ids): ilPropertyFormGUI
557  {
558  $form = new ilPropertyFormGUI();
559  $form->setTitle($this->lng->txt('mail_invite_users_to_chat'));
560  $form->addCommandButton('submitInvitation', $this->lng->txt('submit'));
561  $form->addCommandButton('showContacts', $this->lng->txt('cancel'));
562  $form->setFormAction($this->ctrl->getFormAction($this, 'showContacts'));
563 
564  $sel = new ilSelectInputGUI($this->lng->txt('chat_select_room'), 'room_id');
565  $sel->setOptions($options);
566  $form->addItem($sel);
567 
568  $hidden = new ilHiddenInputGUI('usr_ids');
569  $hidden->setValue(implode(',', $usr_ids));
570  $form->addItem($hidden);
571 
572  return $form;
573  }
574 
578  private function chatroomInvitationMessage(): array
579  {
580  $has = $this->http->wrapper()->query()->has(...);
581  if (!$has('inv_room_ref_id') || !$has('inv_usr_ids')) {
582  return [];
583  }
584 
585  $inv_room_ref_id = $this->http->wrapper()->query()->retrieve(
586  'inv_room_ref_id',
587  $this->refinery->kindlyTo()->int()
588  );
589  $inv_usr_ids = $this->http->wrapper()->query()->retrieve(
590  'inv_usr_ids',
591  $this->refinery->in()->series([
592  $this->refinery->kindlyTo()->string(),
593  $this->refinery->custom()->transformation(fn(string $s): array => explode(',', $s)),
594  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
595  $this->refinery->custom()->constraint(fn(array $a): bool => $a !== [], fn(): string => 'Empty array.'),
596  ])
597  );
598 
599  $userlist = array_map(ilObjUser::_lookupLogin(...), $inv_usr_ids);
600 
601  $url = ilLink::_getStaticLink($inv_room_ref_id, 'chtr');
602 
603  return [
604  $this->ui_factory->messageBox()->success(
605  $this->lng->txt('chat_users_have_been_invited') . $this->ui_renderer->render(
606  $this->ui_factory->listing()->unordered($userlist)
607  )
608  )->withButtons([
609  $this->ui_factory->button()->standard($this->lng->txt('goto_invitation_chat'), $url)
610  ])
611  ];
612  }
613 
617  private function contactAction(): Closure
618  {
619  $url = new URLBuilder(new URI(rtrim(ILIAS_HTTP_PATH, '/') . '/' . $this->ctrl->getLinkTarget($this, 'updateState')));
620  [$url, $p, $token] = $url->acquireParameters(['contact'], 'action', 'user_ids');
621 
622  return fn(string $type, string $lang_var, string $param): Action => $this->ui_factory->table()->action()->$type(
623  $this->lng->txt($lang_var),
624  $url->withParameter($p, $param),
625  $token
626  );
627  }
628 }
final const string CONTACTS_VIEW_TABLE
asErrorMessage(array $array, string $title)
readonly ILIAS HTTP GlobalHttpState $http
changeContactsView()
This method is used to switch the contacts view between gallery and table in the mail system...
ILIAS UI Factory $ui_factory
mailToUsers(array $usr_ids)
$relation
This class represents a selection list property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
updateRelationState(int $user, string $action)
Help GUI class.
inviteToChatForm(array $options, array $usr_ids)
ilUsersGalleryGUI: ilPublicUserProfileGUI ilUsersGalleryGUI: ilCourseMembershipGUI, ilGroupMembershipGUI
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupPref(int $a_usr_id, string $a_keyword)
$url
Definition: shib_logout.php:68
setOptions(array $a_options)
Class ilBuddySystemException.
inviteToChat(array $usr_ids)
ilCtrlInterface $ctrl
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
ilGlobalTemplateInterface $tpl
This class represents a hidden form property in a property form.
GUI class for public user profile presentation.
$ref_id
Definition: ltiauth.php:65
static http()
Fetches the global http state from ILIAS.
readonly RelationsTable $relations_table
final const string CONTACTS_VIEW_GALLERY
static checkPermissionsOfUser(int $usr_id, $permissions, int $ref_id)
Checks user permissions in question for a given user id in relation to a given ref_id.
$token
Definition: xapitoken.php:70
activateTab(string $a_id)
$param
Definition: xapitoken.php:46
ilFormatMail $umail
global $DIC
Definition: shib_login.php:26
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
ilToolbarGUI $toolbar
static byRoomId(int $room_id, bool $initObject=false)
__construct(string $format_mail_class=ilFormatMail::class, string $relations_table_class=RelationsTable::class)
static _isAnonymous(int $usr_id)
ilRbacSystem $rbacsystem
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
ILIAS UI Renderer $ui_renderer
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$message
Definition: xapiexit.php:31
static yn2tf(string $a_yn)
ilErrorHandling $error
URLBuilder.
Definition: URLBuilder.php:40
static getInstanceByGlobalUser(?ilObjUser $user=null)
static _lookupLogin(int $a_user_id)