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