ILIAS  trunk Revision v11.0_alpha-1753-gb21ca8c4367
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilConsultationHoursGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
28 
35 {
36  public const VIEW_MODE_PERIOD_UPCOMING = 'upcoming';
37  public const VIEW_MODE_PERIOD_PAST = 'past';
38  public const VIEW_MODE_PERIOD_ALL = 'all';
39 
40  public const VIEW_MODE_STATUS_BOOKED = 'booked';
41  public const VIEW_MODE_STATUS_OPEN = 'open';
42  public const VIEW_MODE_STATUS_ALL = 'all';
43 
44  protected const MODE_CREATE = 1;
45  protected const MODE_UPDATE = 2;
46  protected const MODE_MULTI = 3;
47 
48  protected const MAX_APPOINTMENTS_PER_SEQUENCE = 1000;
49 
51  protected ilLanguage $lng;
54  protected ilHelpGUI $help;
55  protected ilTabsGUI $tabs;
61 
62 
63 
64 
65  private int $user_id;
66  private bool $search_assignment_to_appointments = false;
68 
70 
71  private string $vm_period = '';
72  private string $vm_status = '';
73 
77  public function __construct()
78  {
79  global $DIC;
80 
81  $this->http = $DIC->http();
82  $this->refinery = $DIC->refinery();
83 
84  $user_id = 0;
85  if ($this->http->wrapper()->query()->has('user_id')) {
86  $user_id = $this->http->wrapper()->query()->retrieve(
87  'user_id',
88  $this->refinery->kindlyTo()->int()
89  );
90  }
91  if ($user_id) {
92  if (in_array($user_id, array_keys(ilConsultationHourAppointments::getManagedUsers()))) {
93  $this->user_id = $user_id;
94  } else {
95  $user_id = false;
96  }
97  }
98  if (!$user_id) {
99  $this->user_id = $DIC->user()->getId();
100  }
101 
102  $this->ctrl = $DIC->ctrl();
103  $this->lng = $DIC->language();
104  $this->tpl = $DIC->ui()->mainTemplate();
105  $this->help = $DIC->help();
106  $this->tabs = $DIC->tabs();
107  $this->toolbar = $DIC->toolbar();
108  $this->global_user = $DIC->user();
109  $this->ui_factory = $DIC->ui()->factory();
110  $this->ui_renderer = $DIC->ui()->renderer();
111  }
112 
113  protected function initSearchAssignmentToAppointments($a_default = false): bool
114  {
115  $this->search_assignment_to_appointments = $a_default;
116  if ($this->http->wrapper()->query()->has('assignM')) {
117  $this->search_assignment_to_appointments = $this->http->wrapper()->query()->retrieve(
118  'assignM',
119  $this->refinery->kindlyTo()->bool()
120  );
121  }
123  }
124 
125  protected function initAppointmentIdsFromTableAction(): array
126  {
127  $current_user_id = $this->getUserId();
128  return $this->http->wrapper()->query()->retrieve(
129  BookingTableGUI::ID_TOKEN_NS,
130  $this->refinery->byTrying(
131  [
132  $this->refinery->custom()->transformation(function ($value) use ($current_user_id) {
133  if ($value !== ['ALL_OBJECTS']) {
134  throw new Exception('Invalid token');
135  }
136  return ilConsultationHourAppointments::getAppointmentIds($current_user_id);
137  }),
138  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
139  $this->refinery->always([])
140  ]
141  )
142  );
143  }
144 
145  protected function initAppointmentIdsFromQuery(): array
146  {
147  if ($this->http->wrapper()->query()->has('apps')) {
148  return [$this->http->wrapper()->query()->retrieve('apps', $this->refinery->kindlyTo()->int())];
149  }
150  return [];
151  }
152 
153  protected function initAppointmentIdsFromPost(): array
154  {
155  if ($this->http->wrapper()->post()->has('apps')) {
156  return $this->http->wrapper()->post()->retrieve(
157  'apps',
158  $this->refinery->kindlyTo()->dictOf(
159  $this->refinery->kindlyTo()->int()
160  )
161  );
162  }
163  return [];
164  }
165 
166  protected function initAppointmentIdsFromPostString(): array
167  {
168  if ($this->http->wrapper()->post()->has('apps_string')) {
169  $app_string = $this->http->wrapper()->post()->retrieve(
170  'apps_string',
171  $this->refinery->kindlyTo()->string()
172  );
173  return array_map('intval', explode(';', $app_string));
174  }
175  return [];
176  }
177 
181  protected function initBookingUsersFromPost(): array
182  {
183  if ($this->http->wrapper()->post()->has('bookuser')) {
184  return $this->http->wrapper()->post()->retrieve(
185  'bookuser',
186  $this->refinery->kindlyTo()->dictOf(
187  $this->refinery->kindlyTo()->string()
188  )
189  );
190  }
191  return [];
192  }
193 
197  protected function initBookingUsersFromQuery(): array
198  {
199  if ($this->http->wrapper()->query()->has('bookuser')) {
200  return [
201  $this->http->wrapper()->query()->retrieve(
202  'bookuser',
203  $this->refinery->kindlyTo()->string()
204  )
205  ];
206  }
207  return [];
208  }
209 
210  public function executeCommand(): void
211  {
212  $this->help->setScreenIdComponent("cal");
213  switch ($this->ctrl->getNextClass($this)) {
214  case "ilpublicuserprofilegui":
215  #22168 don't send the current user if no GET user_id
216  //$profile = new ilPublicUserProfileGUI($this->user_id);
217  $profile = new ilPublicUserProfileGUI();
218  $profile->setBackUrl($this->getProfileBackUrl());
219  $ret = $this->ctrl->forwardCommand($profile);
220  $this->tpl->setContent($ret);
221  break;
222 
223  case 'ilrepositorysearchgui':
224  $rep_search = new ilRepositorySearchGUI();
225  if ($this->initSearchAssignmentToAppointments()) {
226  $rep_search->setCallback(
227  $this,
228  'assignUsersToAppointments',
229  array()
230  );
231  $this->ctrl->setParameter($this, 'assignM', 1);
232  $this->ctrl->setReturn($this, 'appointments');
233  } elseif (count($this->initAppointmentIdsFromPost())) {
234  $rep_search->setCallback(
235  $this,
236  'assignUsersToAppointment',
237  array()
238  );
239  $this->ctrl->saveParameter($this, 'apps');
240  $this->ctrl->setReturn($this, 'appointments');
241  } elseif ($this->initAppointmentIdsFromQuery()) {
242  $rep_search->setCallback(
243  $this,
244  'assignUsersToAppointment',
245  array()
246  );
247  $this->ctrl->saveParameter($this, 'apps');
248  $this->ctrl->setReturn($this, 'appointments');
249  }
250  $this->ctrl->forwardCommand($rep_search);
251  break;
252 
253  default:
254  $this->tpl->setTitle($this->lng->txt("cal_ch_form_header")); // #12220
255 
256  $this->setTabs();
257  if ($this->global_user->getId() != $this->user_id) {
258  $this->ctrl->setParameter($this, 'user_id', $this->user_id);
259  }
260  $cmd = $this->ctrl->getCmd('appointments');
261  $this->$cmd();
262  }
263  }
264 
265  public function getUserId(): int
266  {
267  return $this->user_id;
268  }
269 
270  protected function searchUsersForAppointments(): void
271  {
272  $apps = $this->initAppointmentIdsFromTableAction();
273  if ($apps === []) {
274  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
275  $this->ctrl->redirect($this, 'appointments');
276  }
277  ilSession::set('ch_apps', $apps);
278  $this->ctrl->setParameterByClass(ilConsultationHoursGUI::class, 'assignM', 1);
279  $this->ctrl->redirectByClass(ilRepositorySearchGUI::class, '');
280  }
281 
286  protected function sendInfoAboutUnassignedUsers(array $unassigned): bool
287  {
288  if (!$unassigned) {
289  return true;
290  }
291  $users = array();
292  foreach ($unassigned as $user_id) {
293  $users[] = ilObjUser::_lookupFullname($user_id);
294  }
295  $this->tpl->setOnScreenMessage('info', $this->lng->txt('cal_ch_user_assignment_failed_info') .
296  '<br />' . implode('<br />', $users), true);
297  return true;
298  }
299 
303  public function assignUsersToAppointments(array $users)
304  {
305  $unassigned_users = [];
306  $ch_apps = (array) (ilSession::get('ch_apps') ?? []);
307  foreach ($ch_apps as $app) {
308  $unassigned_users = array_unique(array_merge(
309  $unassigned_users,
310  $this->assignUsersToAppointment($users, $app, false)
311  ));
312  }
313 
314  $this->sendInfoAboutUnassignedUsers($unassigned_users);
315  $this->ctrl->redirect($this, 'appointments');
316  }
317 
326  public function assignUsersToAppointment(array $users, int $a_app = 0, bool $a_redirect = true): array
327  {
328  if ($a_app) {
329  $app = $a_app;
330  } elseif ($this->initBookingUsersFromPost() !== []) {
331  $app = $this->initAppointmentIdsFromPost();
332  $app = current($app);
333  } elseif ($this->initAppointmentIdsFromQuery() !== []) {
334  $app = $this->initAppointmentIdsFromQuery();
335  $app = current($app);
336  }
337  if (!count($users)) {
338  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
339  return [];
340  }
342  $assigned_users = array();
343  foreach ($users as $user) {
344  if ($booking->getCurrentNumberOfBookings($app) >= $booking->getNumberOfBookings()) {
345  break;
346  }
347  if (!ilBookingEntry::lookupBookingsOfUser((array) $app, $user)) {
349  $assigned_users[] = $user;
350  }
351  }
352  $unassigned_users = array_diff($users, $assigned_users);
353  if ($a_redirect) {
354  $this->sendInfoAboutUnassignedUsers($unassigned_users);
355  $this->ctrl->redirect($this, 'appointments');
356  } else {
357  return $unassigned_users;
358  }
359  return [];
360  }
361 
362 
363 
364 
365 
366 
367 
368 
372  protected function bookingList(): void
373  {
374  $this->help->setScreenId("consultation_hours");
375 
376  $btable = new ilConsultationHourBookingTableGUI($this, 'bookingList', $this->getUserId());
378  $this->tpl->setContent($btable->getHTML());
379  }
380 
384  protected function confirmDeleteBooking(): void
385  {
386  $this->confirmRejectBooking(false);
387  }
388 
392  protected function confirmRejectBooking(bool $a_send_notification = true): void
393  {
394  $bookusers = [];
395  if ($this->initBookingUsersFromPost() !== []) {
396  $bookusers = $this->initBookingUsersFromPost();
397  } elseif ($this->initBookingUsersFromQuery() !== []) {
398  $bookusers = $this->initBookingUsersFromQuery();
399  }
400 
401  if ($bookusers === []) {
402  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
403  $this->bookingList();
404  return;
405  }
406 
407  $confirm = new ilConfirmationGUI();
408  $confirm->setFormAction($this->ctrl->getFormAction($this));
409 
410  if ($a_send_notification) {
411  $this->tpl->setOnScreenMessage('info', $this->lng->txt('cal_ch_cancel_booking_info'));
412  $confirm->setHeaderText($this->lng->txt('cal_ch_cancel_booking_sure'));
413  $confirm->setConfirm($this->lng->txt('cal_ch_reject_booking'), 'rejectBooking');
414  } else {
415  $this->tpl->setOnScreenMessage('info', $this->lng->txt('cal_ch_delete_booking_info'));
416  $confirm->setHeaderText($this->lng->txt('cal_ch_delete_booking_sure'));
417  $confirm->setConfirm($this->lng->txt('cal_ch_delete_booking'), 'deleteBooking');
418  }
419 
420  $confirm->setCancel($this->lng->txt('cancel'), 'bookingList');
421 
422  foreach ($bookusers as $bookuser) {
423  $ids = explode('_', $bookuser);
424 
425  $entry = new ilCalendarEntry((int) $ids[0]);
426  $confirm->addItem(
427  'bookuser[]',
428  $bookuser,
430  $ids[1],
431  true,
432  false,
433  '',
434  true,
435  true
436  ) . ', ' . ilDatePresentation::formatDate($entry->getStart())
437  );
438  }
439  $this->tpl->setContent($confirm->getHTML());
440  }
441 
445  protected function createSequence(): void
446  {
447  $this->initFormSequence(self::MODE_CREATE);
448 
449  $this->booking = new ilBookingEntry();
450  $this->form->getItemByPostVar('bo')->setValue((string) $this->booking->getNumberOfBookings());
451  $this->form->getItemByPostVar('ap')->setValue("1");
452  $this->form->getItemByPostVar('du')->setMinutes(15);
453  $this->form->getItemByPostVar('st')->setDate(
454  new ilDateTime(mktime(8, 0, 0, (int) date('n', time()), (int) date('d', time()), (int) date('Y', time())), IL_CAL_UNIX)
455  );
456  $this->tpl->setContent($this->form->getHTML());
457  }
458 
462  protected function initFormSequence(int $a_mode): ilPropertyFormGUI
463  {
465 
466  $this->form = new ilPropertyFormGUI();
467  $this->form->setFormAction($this->ctrl->getFormAction($this));
468 
469  switch ($a_mode) {
470  case self::MODE_CREATE:
471  $this->form->setTitle($this->lng->txt('cal_ch_add_sequence'));
472  $this->form->addCommandButton('saveSequence', $this->lng->txt('save'));
473  $this->form->addCommandButton('appointments', $this->lng->txt('cancel'));
474  break;
475 
476  case self::MODE_MULTI:
477  $this->form->setTitle($this->lng->txt('cal_ch_multi_edit_sequence'));
478  $this->form->addCommandButton('updateMulti', $this->lng->txt('save'));
479  $this->form->addCommandButton('appointments', $this->lng->txt('cancel'));
480  break;
481  }
482 
483  // Title
484  $ti = new ilTextInputGUI($this->lng->txt('title'), 'ti');
485  $ti->setSize(32);
486  $ti->setMaxLength(128);
487  $ti->setRequired(true);
488  $this->form->addItem($ti);
489 
490  if ($a_mode != self::MODE_MULTI) {
491  // Start
492  $dur = new ilDateTimeInputGUI($this->lng->txt('cal_start'), 'st');
493  $dur->setShowTime(true);
494  $dur->setRequired(true);
495  $this->form->addItem($dur);
496 
497  // Duration
498  $du = new ilDurationInputGUI($this->lng->txt('cal_ch_duration'), 'du');
499  $du->setShowMinutes(true);
500  $du->setShowHours(true);
501  $this->form->addItem($du);
502 
503  // Number of appointments
504  $nu = new ilNumberInputGUI($this->lng->txt('cal_ch_num_appointments'), 'ap');
505  $nu->setInfo($this->lng->txt('cal_ch_num_appointments_info'));
506  $nu->setSize(2);
507  $nu->setMaxLength(2);
508  $nu->setRequired(true);
509  $nu->setMinValue(1);
510  $this->form->addItem($nu);
511 
512  // Recurrence
513  $rec = new ilRecurrenceInputGUI($this->lng->txt('cal_recurrences'), 'frequence');
514  $rec->setEnabledSubForms(
515  array(
519  )
520  );
521  $this->form->addItem($rec);
522  }
523 
524  // Number of bookings
525  $nu = new ilNumberInputGUI($this->lng->txt('cal_ch_num_bookings'), 'bo');
526  $nu->setSize(2);
527  $nu->setMaxLength(2);
528  $nu->setMinValue(1);
529  $nu->setRequired(true);
530  $this->form->addItem($nu);
531 
532  // Deadline
533  $dead = new ilDurationInputGUI($this->lng->txt('cal_ch_deadline'), 'dead');
534  $dead->setInfo($this->lng->txt('cal_ch_deadline_info'));
535  $dead->setShowMinutes(false);
536  $dead->setShowHours(true);
537  $dead->setShowDays(true);
538  $this->form->addItem($dead);
539 
540  // Location
541  $lo = new ilTextInputGUI($this->lng->txt('cal_where'), 'lo');
542  $lo->setSize(32);
543  $lo->setMaxLength(128);
544  $this->form->addItem($lo);
545 
546  // Description
547  $de = new ilTextAreaInputGUI($this->lng->txt('description'), 'de');
548  $de->setRows(10);
549  $de->setCols(60);
550  $this->form->addItem($de);
551 
552  // Target Object
553  $tgt = new ilTextInputGUI($this->lng->txt('cal_ch_target_object'), 'tgt');
554  $tgt->setInfo($this->lng->txt('cal_ch_target_object_info'));
555  $tgt->setSize(16);
556  $tgt->setMaxLength(128);
557  $this->form->addItem($tgt);
558  return $this->form;
559  }
560 
564  protected function saveSequence(): void
565  {
566  $this->initFormSequence(self::MODE_CREATE);
567 
568  if ($this->form->checkInput()) {
569  $this->form->setValuesByPost();
570 
571  $booking = new ilBookingEntry();
572  $booking->setObjId($this->getUserId());
573  $booking->setNumberOfBookings((int) $this->form->getInput('bo'));
574 
575  $deadline = $this->form->getInput('dead');
576  $deadline = $deadline['dd'] * 24 + $deadline['hh'];
577  $booking->setDeadlineHours($deadline);
578 
579  $tgt = array_map('intval', explode(',', $this->form->getInput('tgt')));
580  $obj_ids = array();
581  foreach ($tgt as $ref_id) {
582  if ($ref_id === 0) {
583  continue;
584  }
585  $obj_id = ilObject::_lookupObjId($ref_id);
586  $type = ilObject::_lookupType($obj_id);
587  $valid_types = array('crs', 'grp');
588  if (!$obj_id or !in_array($type, $valid_types)) {
589  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cal_ch_unknown_repository_object'));
590  $this->tpl->setContent($this->form->getHTML());
591  return;
592  }
593 
594  $obj_ids[] = $obj_id;
595  }
596  $booking->setTargetObjIds($obj_ids);
597  $booking->save();
598  $this->createAppointments($booking);
599  $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
600  $this->ctrl->redirect($this, 'appointments');
601  } else {
602  $this->form->setValuesByPost();
603  $this->tpl->setContent($this->form->getHTML());
604  }
605  }
606 
610  protected function createAppointments(ilBookingEntry $booking): void
611  {
612  $concurrent_dates = new ilDateList(ilDateList::TYPE_DATETIME);
613  $start = clone $this->form->getItemByPostVar('st')->getDate();
614  for ($i = 0; $i < $this->form->getItemByPostVar('ap')->getValue(); $i++) {
615  $concurrent_dates->add(clone $start);
616 
617  $start->increment(ilDateTime::MINUTE, $this->form->getItemByPostVar('du')->getMinutes());
618  $start->increment(ilDateTime::HOUR, $this->form->getItemByPostVar('du')->getHours());
619  #$start = new ilDateTime(,IL_CAL_UNIX);
620  }
621 
624  $this->getUserId(),
625  $this->lng->txt('cal_ch_personal_ch'),
626  true
627  );
628 
629  // Add calendar appointment for each
630 
631  $num_appointments = 0;
632  foreach ($concurrent_dates as $dt) {
633  if ($num_appointments >= self::MAX_APPOINTMENTS_PER_SEQUENCE) {
634  break;
635  }
636 
637  $end = clone $dt;
638  $end->increment(ilDateTime::MINUTE, $this->form->getItemByPostVar('du')->getMinutes());
639  $end->increment(ilDateTime::HOUR, $this->form->getItemByPostVar('du')->getHours());
640 
641  $calc = new ilCalendarRecurrenceCalculator(
642  new ilBookingPeriod($dt, $end),
643  $this->form->getItemByPostVar('frequence')->getRecurrence()
644  );
645 
646  // Calculate with one year limit
647  $limit = clone $dt;
648  $limit->increment(ilDateTime::YEAR, 1);
649 
650  $date_list = $calc->calculateDateList($dt, $limit);
651 
652  $num = 0;
653  foreach ($date_list as $app_start) {
654  $app_end = clone $app_start;
655  $app_end->increment(ilDateTime::MINUTE, $this->form->getItemByPostVar('du')->getMinutes());
656  $app_end->increment(ilDateTime::HOUR, $this->form->getItemByPostVar('du')->getHours());
657 
658  $entry = new ilCalendarEntry();
659  $entry->setContextId($booking->getId());
660  $entry->setTitle($this->form->getInput('ti'));
661  $entry->setSubtitle("#consultationhour#"); // dynamic, see ilCalendarEntry
662  $entry->setDescription($this->form->getInput('de'));
663  $entry->setLocation($this->form->getInput('lo'));
664  $entry->setStart($app_start);
665  $entry->setEnd($app_end);
666 
667  $entry->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
668  $entry->save();
669 
670  $cat_assign = new ilCalendarCategoryAssignments($entry->getEntryId());
671  $cat_assign->addAssignment($def_cat->getCategoryID());
672 
673  $num_appointments++;
674  }
675  }
676  }
677 
678  protected function setTabs(): void
679  {
680  $this->ctrl->setParameter($this, 'user_id', '');
681  $this->tabs->addTab(
682  'consultation_hours_' . $this->user_id,
683  $this->lng->txt('cal_ch_ch'),
684  $this->ctrl->getLinkTarget($this, 'appointments')
685  );
686 
687  foreach (ilConsultationHourAppointments::getManagedUsers() as $user_id => $login) {
688  $this->ctrl->setParameter($this, 'user_id', $user_id);
689  $this->tabs->addTab(
690  'consultation_hours_' . $user_id,
691  $this->lng->txt('cal_ch_ch') . ': ' . $login,
692  $this->ctrl->getLinkTarget($this, 'appointments')
693  );
694  }
695  $this->ctrl->setParameter($this, 'user_id', '');
696  $this->tabs->addTab('ch_settings', $this->lng->txt('settings'), $this->ctrl->getLinkTarget($this, 'settings'));
697  $this->tabs->activateTab('consultation_hours_' . $this->getUserId());
698  }
699 
700  public function edit(): void
701  {
702  $apps = $this->initAppointmentIdsFromTableAction();
703  if (!count($apps)) {
704  if ($this->initAppointmentIdsFromPostString() !== []) {
705  $apps = $this->initAppointmentIdsFromPostString();
706  }
707  }
708 
709  // first read from hidden input
710  if (!count($apps)) {
711  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
712  $this->appointments();
713  return;
714  }
715 
716  $this->initFormSequence(self::MODE_MULTI);
717  $hidden = new ilHiddenInputGUI('apps_string');
718  $hidden->setValue(implode(';', $apps));
719  $this->form->addItem($hidden);
720 
721  $first = $apps;
722  $first = array_shift($apps);
723  $entry = new ilCalendarEntry($first);
724 
725  $this->form->getItemByPostVar('ti')->setValue($entry->getTitle());
726  $this->form->getItemByPostVar('lo')->setValue($entry->getLocation());
727  $this->form->getItemByPostVar('de')->setValue($entry->getDescription());
728 
729  $booking = new ilBookingEntry($entry->getContextId());
730 
731  $this->form->getItemByPostVar('bo')->setValue((string) $booking->getNumberOfBookings());
732 
733  $ref_ids = array();
734  foreach ($booking->getTargetObjIds() as $obj_id) {
735  $refs = ilObject::_getAllReferences($obj_id);
736  $ref_ids[] = end($refs);
737  }
738  $this->form->getItemByPostVar('tgt')->setValue(implode(',', $ref_ids));
739 
740  $deadline = $booking->getDeadlineHours();
741  $this->form->getItemByPostVar('dead')->setDays((int) floor($deadline / 24));
742  $this->form->getItemByPostVar('dead')->setHours($deadline % 24);
743  $this->tpl->setContent($this->form->getHTML());
744  }
745 
746  protected function createNewBookingEntry(ilPropertyFormGUI $validate_form): ?ilBookingEntry
747  {
748  $booking = new \ilBookingEntry();
749  $booking->setObjId($this->user_id);
750  $booking->setNumberOfBookings((int) $this->form->getInput('bo'));
751 
752  $deadline = $this->form->getInput('dead');
753  $deadline = $deadline['dd'] * 24 + $deadline['hh'];
754  $booking->setDeadlineHours($deadline);
755 
756  $tgt = array_map('intval', explode(',', (string) $this->form->getInput('tgt')));
757  $obj_ids = [];
758  foreach ($tgt as $ref_id) {
759  if ($ref_id === 0) {
760  continue;
761  }
762  $obj_id = ilObject::_lookupObjId($ref_id);
763  $type = ilObject::_lookupType($obj_id);
764  $valid_types = ['crs', 'grp'];
765  if (!$obj_id or !in_array($type, $valid_types)) {
766  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cal_ch_unknown_repository_object'));
767  return null;
768  }
769  $obj_ids[] = $obj_id;
770  }
771  $booking->setTargetObjIds($obj_ids);
772  $booking->save();
773  return $booking;
774  }
775 
777  ilBookingEntry $booking,
778  array $appointments,
779  ilPropertyFormGUI $form
780  ): void {
781  foreach ($appointments as $appointment_id) {
782  $booking_appointment = new \ilCalendarEntry($appointment_id);
783  $booking_start = $booking_appointment->getStart();
784  $booking_end = $booking_appointment->getEnd();
785 
786  $deprecatedBooking = \ilBookingEntry::getInstanceByCalendarEntryId($appointment_id);
787  if (!$deprecatedBooking instanceof \ilBookingEntry) {
788  // @todo error handling
789  continue;
790  }
791 
793  $deprecatedBooking,
794  $booking_start,
795  $booking_end
796  );
797  foreach ($relevant_appointments as $relevant_appointment_id) {
798  $entry = new \ilCalendarEntry($relevant_appointment_id);
799  $entry->setContextId($booking->getId());
800  $entry->setTitle($form->getInput('ti'));
801  $entry->setLocation($form->getInput('lo'));
802  $entry->setDescription($form->getInput('de'));
803  $entry->update();
804  }
805  }
806  }
807 
811  protected function updateMulti(): void
812  {
813  $this->initFormSequence(self::MODE_MULTI);
814  if (!$this->form->checkInput()) {
815  $this->form->setValuesByPost();
816  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
817  $this->edit();
818  return;
819  }
820 
821  $this->form->setValuesByPost();
822  $apps = $this->initAppointmentIdsFromPostString();
823 
824  // create new booking
825  $booking = $this->createNewBookingEntry($this->form);
826  if (!$booking instanceof \ilBookingEntry) {
827  $this->edit();
828  return;
829  }
830  $this->rewriteBookingIdsForAppointments($booking, $apps, $this->form);
832 
833  $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
834  $this->ctrl->redirect($this, 'appointments');
835  $this->tpl->setContent($this->form->getHTML());
836  }
837 
841  public function showProfile(): void
842  {
843  $this->tabs->clearTargets();
844 
845  $user_id = 0;
846  if ($this->http->wrapper()->query()->has('user')) {
847  $user_id = $this->http->wrapper()->query()->retrieve(
848  'user',
849  $this->refinery->kindlyTo()->int()
850  );
851  }
852  $profile = new ilPublicUserProfileGUI($user_id);
853  $profile->setBackUrl($this->getProfileBackUrl());
854  $this->tpl->setContent($this->ctrl->getHTML($profile));
855  }
856 
860  protected function getProfileBackUrl(): string
861  {
862  // from repository
863  if ($this->http->wrapper()->query()->has('ref_id')) {
864  $url = $this->ctrl->getLinkTargetByClass('ilCalendarMonthGUI');
865  } // from panel
866  elseif ($this->http->wrapper()->query()->has('panel')) {
867  $url = $this->ctrl->getLinkTargetByClass('ilCalendarPresentationGUI');
868  } // from appointments
869  else {
870  $url = $this->ctrl->getLinkTarget($this, 'appointments');
871  }
872  return $url;
873  }
874 
878  public function settings(): void
879  {
880  $this->help->setScreenId("consultation_hours_settings");
881  $this->tabs->activateTab('ch_settings');
882 
883  $form = $this->initSettingsForm();
884  $this->tpl->setContent($form->getHTML());
885  }
886 
890  protected function initSettingsForm(): ilPropertyFormGUI
891  {
892  $form = new ilPropertyFormGUI();
893  $form->setFormAction($this->ctrl->getFormAction($this));
894 
895  $mng = new ilTextInputGUI($this->lng->txt('cal_ch_manager'), 'mng');
896  $mng->setInfo($this->lng->txt('cal_ch_manager_info'));
897  $form->addItem($mng);
898 
899  $mng->setValue(ilConsultationHourAppointments::getManager(true));
900 
901  $form->setTitle($this->lng->txt('settings'));
902  $form->addCommandButton('updateSettings', $this->lng->txt('save'));
903  return $form;
904  }
905 
909  public function updateSettings(): void
910  {
911  $form = $this->initSettingsForm();
912  if ($form->checkInput()) {
913  $mng = $form->getInput('mng');
915  $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
916  $this->ctrl->redirect($this, 'settings');
917  } else {
918  $this->tabs->activateTab('ch_settings');
919 
920  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cal_ch_unknown_user'));
921  $field = $form->getItemByPostVar('mng');
922  $field->setValue($mng);
923  $this->tpl->setContent($form->getHTML());
924  return;
925  }
926  }
927  }
928 
929  protected function appointments(): void
930  {
931  $this->initViewMode();
932  $table = new BookingTableGUI(
933  new BookingDataProvider($this->getUserId(), $this->vm_period, $this->vm_status)
934  );
935  $this->tpl->setContent(
936  $this->renderViewControl() .
937  $table->render()
938  );
939  }
940 
941 
942  protected function handleBookingTableActions(): void
943  {
944  $action = $this->http->wrapper()->query()->retrieve(
945  BookingTableGUI::ACTION_TOKEN_NS,
946  $this->refinery->byTrying(
947  [
948  $this->refinery->kindlyTo()->string(),
949  $this->refinery->always('')
950  ]
951  )
952  );
953  match ($action) {
954  'edit' => $this->edit(),
955  'searchUsersForAppointments' => $this->searchUsersForAppointments(),
956  'confirmDeleteAppointments' => $this->confirmDeleteAppointments(),
957  'confirmCancelBooking' => $this->confirmCancelBooking(true),
958  'confirmDeleteBooking' => $this->confirmCancelBooking(false),
959  'sendMail' => $this->sendMailToSelectedUsers(),
960  default => $this->ctrl->redirect($this, 'appointments')
961  };
962  }
963 
964  protected function sendMailToSelectedUsers(): void
965  {
966  $appointment_ids = $this->initAppointmentIdsFromTableAction();
967  if ($appointment_ids === []) {
968  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
969  $this->appointments();
970  return;
971  }
972 
973  $bookusers = [];
974  foreach ($appointment_ids as $appointment_id) {
975  $entry = new ilCalendarEntry($appointment_id);
976  $booking = new ilBookingEntry($entry->getContextId());
977  foreach ($booking->getCurrentBookings($entry->getEntryId()) as $bookuser) {
978  $login = ilObjUser::_lookupLogin($bookuser);
979  if (!in_array($login, $bookusers)) {
980  $bookusers[] = $login;
981  }
982  }
983  }
984  $this->ctrl->redirectToURL(
986  $this,
987  'appointments',
988  [],
989  [
990  'type' => 'new',
991  'rcp_to' => implode(',', $bookusers)
992  ]
993  )
994  );
995  }
996 
997  protected function confirmCancelBooking(bool $with_notification = true): void
998  {
999  $appointment_ids = $this->initAppointmentIdsFromTableAction();
1000  if ($appointment_ids === []) {
1001  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1002  $this->appointments();
1003  return;
1004  }
1005 
1006  $appointment = end($appointment_ids);
1007  $this->ctrl->setParameter($this, 'appointment_id', $appointment);
1008  $entry = new ilCalendarEntry($appointment);
1009  $booking = new ilBookingEntry($entry->getContextId());
1010 
1011  $cancel = new \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI(
1012  $this,
1013  $entry,
1014  $booking,
1015  $with_notification ?
1016  \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_CANCEL :
1017  \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_DELETE
1018  );
1019  $modal = $cancel->renderModal();
1020  $output = $this->ui_renderer->renderAsync($modal);
1021  $this->http->saveResponse($this->http->response()->withBody(
1022  Streams::ofString($output)
1023  ));
1024  $this->http->sendResponse();
1025  $this->http->close();
1026  }
1027 
1028  protected function deleteBooking(): void
1029  {
1030  $this->cancelBooking(false);
1031  }
1032 
1033  protected function cancelBooking(bool $with_notification = true): void
1034  {
1035  $appointment_id = $this->http->wrapper()->query()->retrieve(
1036  'appointment_id',
1037  $this->refinery->byTrying(
1038  [
1039  $this->refinery->kindlyTo()->int(),
1040  $this->refinery->always(0)
1041  ]
1042  )
1043  );
1044  if (!$appointment_id) {
1045  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1046  $this->appointments();
1047  return;
1048  }
1049 
1050  $entry = new ilCalendarEntry($appointment_id);
1051  $booking = new ilBookingEntry($entry->getContextId());
1052  $cancel = new \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI(
1053  $this,
1054  $entry,
1055  $booking,
1056  $with_notification ?
1057  \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_CANCEL :
1058  \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_DELETE
1059  );
1060  $data = $cancel->renderModal()->withRequest($this->http->request())->getData();
1061  foreach ((array) $data['bookings'] as $user => $checked) {
1062  if ($checked) {
1064  $user,
1065  $appointment_id,
1066  $with_notification
1067  );
1068  }
1069  }
1070  $this->tpl->setOnScreenMessage('success', $this->lng->txt('cal_ch_canceled_bookings'), true);
1071  $this->ctrl->redirect($this, 'appointments');
1072  }
1073 
1074  protected function confirmDeleteAppointments(): void
1075  {
1076  $appointment_ids = $this->initAppointmentIdsFromTableAction();
1077  if (!count($appointment_ids)) {
1078  $output = $this->ui_factory->messageBox()->failure($this->lng->txt('select_one'));
1079  } else {
1080  $items = [];
1081  foreach ($appointment_ids as $appointment) {
1082  $entry = new ilCalendarEntry($appointment);
1083  $items[] = $this->ui_factory->modal()->interruptiveItem()->standard(
1084  (string) $appointment,
1085  ilDatePresentation::formatDate($entry->getStart()) . ', ' . $entry->getTitle()
1086  );
1087  }
1088 
1089  $output = $this->ui_factory->modal()->interruptive(
1090  $this->lng->txt('confirm'),
1091  $this->lng->txt('cal_ch_delete_app_booking_info'),
1092  $this->ctrl->getFormAction($this, 'deleteAppointments')
1093  )->withAffectedItems($items);
1094  }
1095 
1096  $rendered_output = $this->ui_renderer->renderAsync($output);
1097  $this->http->saveResponse($this->http->response()->withBody(
1098  Streams::ofString($rendered_output)
1099  ));
1100  $this->http->sendResponse();
1101  $this->http->close();
1102  }
1103 
1104  protected function deleteAppointments(): void
1105  {
1106  $appointment_ids = $this->http->wrapper()->post()->retrieve(
1107  'interruptive_items',
1108  $this->refinery->byTrying(
1109  [
1110  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
1111  $this->refinery->always([])
1112  ]
1113  )
1114  );
1115  if (!count($appointment_ids)) {
1116  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1117  $this->appointments();
1118  return;
1119  }
1120 
1121  foreach ($appointment_ids as $appointment_id) {
1122  // cancel booking for users
1123  $booking = ilBookingEntry::getInstanceByCalendarEntryId($appointment_id);
1124  if ($booking) {
1125  foreach ($booking->getCurrentBookings($appointment_id) as $user_id) {
1126  ilConsultationHourUtils::cancelBooking($user_id, $appointment_id, false);
1127  }
1128  }
1129  // remove calendar entries
1130  $entry = new ilCalendarEntry($appointment_id);
1131  $entry->delete();
1133  }
1135  $this->tpl->setOnScreenMessage('success', $this->lng->txt('cal_deleted_app'), true);
1136  $this->ctrl->redirect($this, 'appointments');
1137  }
1138 
1140  {
1141  $add_sequence_button = $this->ui_factory->button()->standard(
1142  $this->lng->txt('cal_ch_add_sequence'),
1143  $this->ctrl->getLinkTarget($this, 'createSequence')
1144  );
1145  return $add_sequence_button;
1146  }
1147 
1148  protected function renderViewControl(): string
1149  {
1150  $toolbar = new ilToolbarGUI();
1151  $toolbar->addComponent($this->initSequenceCreation());
1152  $toolbar->addSeparator();
1153 
1154  $this->ctrl->setParameter($this, 'vm_period', self::VIEW_MODE_PERIOD_PAST);
1155  $actions[$this->lng->txt('cal_ch_vm_period_' . self::VIEW_MODE_PERIOD_PAST)] = $this->ctrl->getLinkTarget(
1156  $this,
1157  'appointments'
1158  );
1159  $this->ctrl->setParameter($this, 'vm_period', self::VIEW_MODE_PERIOD_UPCOMING);
1160  $actions[$this->lng->txt('cal_ch_vm_period_' . self::VIEW_MODE_PERIOD_UPCOMING)] = $this->ctrl->getLinkTarget(
1161  $this,
1162  'appointments'
1163  );
1164  $this->ctrl->setParameter($this, 'vm_period', self::VIEW_MODE_PERIOD_ALL);
1165  $actions[$this->lng->txt('cal_ch_vm_period_' . self::VIEW_MODE_PERIOD_ALL)] = $this->ctrl->getLinkTarget(
1166  $this,
1167  'appointments'
1168  );
1169  $this->ctrl->setParameter($this, 'vm_period', '');
1170 
1171  $view_control_period = $this->ui_factory->viewControl()->mode(
1172  $actions,
1173  $this->lng->txt('meta_aria_language_selection')
1174  )->withActive($this->lng->txt('cal_ch_vm_period_' . $this->vm_period));
1175 
1176  $toolbar->addComponent($view_control_period);
1177 
1178  $actions = [];
1179  $this->ctrl->setParameter($this, 'vm_status', self::VIEW_MODE_STATUS_OPEN);
1180  $actions[$this->lng->txt('cal_ch_vm_status_' . self::VIEW_MODE_STATUS_OPEN)] = $this->ctrl->getLinkTarget(
1181  $this,
1182  'appointments'
1183  );
1184  $this->ctrl->setParameter($this, 'vm_status', self::VIEW_MODE_STATUS_BOOKED);
1185  $actions[$this->lng->txt('cal_ch_vm_status_' . self::VIEW_MODE_STATUS_BOOKED)] = $this->ctrl->getLinkTarget(
1186  $this,
1187  'appointments'
1188  );
1189  $this->ctrl->setParameter($this, 'vm_status', self::VIEW_MODE_STATUS_ALL);
1190  $actions[$this->lng->txt('cal_ch_vm_status_' . self::VIEW_MODE_STATUS_ALL)] = $this->ctrl->getLinkTarget(
1191  $this,
1192  'appointments'
1193  );
1194  $this->ctrl->setParameter($this, 'vm_status', '');
1195 
1196  $view_control_status = $this->ui_factory->viewControl()->mode(
1197  $actions,
1198  $this->lng->txt('meta_aria_language_selection')
1199  )->withActive($this->lng->txt('cal_ch_vm_status_' . $this->vm_status));
1200 
1201  $toolbar->addComponent($view_control_status);
1202  return $toolbar->getHTML();
1203  }
1204 
1205  protected function initViewMode(): void
1206  {
1207  global $DIC;
1208 
1209  $user = $DIC->user();
1210  $vm_period = $this->http->wrapper()->query()->retrieve(
1211  'vm_period',
1212  $this->refinery->byTrying(
1213  [
1214  $this->refinery->kindlyTo()->string(),
1215  $this->refinery->always('')
1216  ]
1217  )
1218  );
1219  $vm_status = $this->http->wrapper()->query()->retrieve(
1220  'vm_status',
1221  $this->refinery->byTrying(
1222  [
1223  $this->refinery->kindlyTo()->string(),
1224  $this->refinery->always('')
1225  ]
1226  )
1227  );
1228 
1229  if ($vm_period !== '') {
1230  $user->writePref('cal_ch_vm_period', $vm_period);
1231  }
1232  if ($vm_status !== '') {
1233  $user->writePref('cal_ch_vm_status', $vm_status);
1234  }
1235  $this->vm_period = $user->getPref('cal_ch_vm_period') ? $user->getPref('cal_ch_vm_period') : self::VIEW_MODE_PERIOD_ALL;
1236  $this->vm_status = $user->getPref('cal_ch_vm_status') ? $user->getPref('cal_ch_vm_status') : self::VIEW_MODE_STATUS_ALL;
1237 
1238  }
1239 
1240 }
showProfile()
show public profile of given user
static get(string $a_var)
This class represents a duration (typical hh:mm:ss) property in a property form.
bookingList()
Show list of bookings.
assignUsersToAppointment(array $users, int $a_app=0, bool $a_redirect=true)
Assign users to an appointment.
rewriteBookingIdsForAppointments(ilBookingEntry $booking, array $appointments, ilPropertyFormGUI $form)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getCurrentBookings(int $a_entry_id)
get current bookings
getItemByPostVar(string $a_post_var)
static _lookupFullname(int $a_user_id)
ilGlobalTemplateInterface $tpl
static getAppointmentIds(int $a_user_id, ?int $a_context_id=null, ?ilDateTime $a_start=null, ?int $a_type=null, bool $a_check_owner=true)
getCurrentNumberOfBookings(int $a_entry_id)
get current number of bookings
assignUsersToAppointments(array $users)
Assign users to multiple appointments.
Interface Observer Contains several chained tasks and infos about them.
This class represents an input GUI for recurring events/appointments (course events or calendar appoi...
static _getAllReferences(int $id)
get all reference ids for object ID
Help GUI class.
static cancelBooking(int $a_usr_id, int $a_app_id, bool $a_send_notification=true)
Cancel a booking.
addComponent(\ILIAS\UI\Component\Component $a_comp)
static initDomEvent(?ilGlobalTemplateInterface $a_main_tpl=null)
Init YUI DomEvent used in Services/Calendar, Modules/Session, Modules/Test (Jan 2022) ...
static removeObsoleteEntries()
Remove unused booking entries.
confirmDeleteBooking()
Show delete booking confirmation.
createNewBookingEntry(ilPropertyFormGUI $validate_form)
setShowTime(bool $a_showtime)
$url
Definition: shib_logout.php:66
const IL_CAL_UNIX
static getManager(bool $a_as_name=false, bool $a_full_name=false, ?int $a_user_id=null)
Get consultation hour manager for current user or specific user.
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
static lookupBookingsOfUser(array $a_app_ids, int $a_usr_id, ?ilDateTime $start=null)
Lookup bookings of user.
This class represents a date/time property in a property form.
static _lookupObjId(int $ref_id)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
createAppointments(ilBookingEntry $booking)
Create calendar appointments.
static getInstanceByCalendarEntryId(int $a_id)
Get instance by calendar entry.
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.
setEnabledSubForms(array $a_sub_forms)
set enabled subforms
confirmRejectBooking(bool $a_send_notification=true)
Show delete booking confirmation.
setDeadlineHours(int $a_hours)
static getNamePresentation( $a_user_id, bool $a_user_image=false, bool $a_profile_link=false, string $a_profile_back_link='', bool $a_force_first_lastname=false, bool $a_omit_login=false, bool $a_sortable=true, bool $a_return_data_array=false, $a_ctrl_path='ilpublicuserprofilegui')
Default behaviour is:
sendInfoAboutUnassignedUsers(array $unassigned)
Send info message about unassigned users.
static getManagedUsers()
Get all managed consultation hours users for current users.
static _deleteByAppointmentId(int $a_app_id)
Delete appointment assignment.
Calculates an ilDateList for a given calendar entry and recurrence rule.
setFormAction(string $a_formaction)
List of dates.
This class represents a number property in a property form.
static initDefaultCalendarByType(int $a_type_id, int $a_usr_id, string $a_title, bool $a_create=false)
Init the default calendar for given type and user.
global $DIC
Definition: shib_login.php:22
cancelBooking(bool $with_notification=true)
addCommandButton(string $a_cmd, string $a_text, string $a_id="")
confirmCancelBooking(bool $with_notification=true)
form( $class_path, string $cmd, string $submit_caption="")
setShowMinutes(bool $a_showminutes)
This class represents a text area property in a property form.
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ?ilObjUser $user=null,)
static getRedirectTarget( $gui, string $cmd, array $gui_params=[], array $mail_params=[], array $context_params=[])
setNumberOfBookings(int $a_num)
initSearchAssignmentToAppointments($a_default=false)
static bookAppointment(int $a_usr_id, int $a_app_id, string $comment='')
Book an appointment.
createSequence()
Create new sequence.
static findCalendarAppointmentsForBooking(ilBookingEntry $booking, ilDateTime $start, ilDateTime $end)
static _lookupType(int $id, bool $reference=false)
setTargetObjIds(?array $a_obj_id)
Booking period Used for calculation of recurring events.
static set(string $a_var, $a_val)
Set a value.
updateMulti()
Update multiple sequence items.
static setManager(string $a_user_name)
Set consultation hour manager for current user.
calculateDateList(ilDateTime $a_start, ilDateTime $a_end, int $a_limit=-1)
calculate date list
getProfileBackUrl()
Build context-sensitive profile back url.
initSettingsForm()
build settings form
static _lookupLogin(int $a_user_id)