ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
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 {
465 $this->form = new ilPropertyFormGUI();
466 $this->form->setFormAction($this->ctrl->getFormAction($this));
467
468 switch ($a_mode) {
470 $this->form->setTitle($this->lng->txt('cal_ch_add_sequence'));
471 $this->form->addCommandButton('saveSequence', $this->lng->txt('save'));
472 $this->form->addCommandButton('appointments', $this->lng->txt('cancel'));
473 break;
474
475 case self::MODE_MULTI:
476 $this->form->setTitle($this->lng->txt('cal_ch_multi_edit_sequence'));
477 $this->form->addCommandButton('updateMulti', $this->lng->txt('save'));
478 $this->form->addCommandButton('appointments', $this->lng->txt('cancel'));
479 break;
480 }
481
482 // Title
483 $ti = new ilTextInputGUI($this->lng->txt('title'), 'ti');
484 $ti->setSize(32);
485 $ti->setMaxLength(128);
486 $ti->setRequired(true);
487 $this->form->addItem($ti);
488
489 if ($a_mode != self::MODE_MULTI) {
490 // Start
491 $dur = new ilDateTimeInputGUI($this->lng->txt('cal_start'), 'st');
492 $dur->setShowTime(true);
493 $dur->setRequired(true);
494 $this->form->addItem($dur);
495
496 // Duration
497 $du = new ilDurationInputGUI($this->lng->txt('cal_ch_duration'), 'du');
498 $du->setShowMinutes(true);
499 $du->setShowHours(true);
500 $this->form->addItem($du);
501
502 // Number of appointments
503 $nu = new ilNumberInputGUI($this->lng->txt('cal_ch_num_appointments'), 'ap');
504 $nu->setInfo($this->lng->txt('cal_ch_num_appointments_info'));
505 $nu->setSize(2);
506 $nu->setMaxLength(2);
507 $nu->setRequired(true);
508 $nu->setMinValue(1);
509 $this->form->addItem($nu);
510
511 // Recurrence
512 $rec = new ilRecurrenceInputGUI($this->lng->txt('cal_recurrences'), 'frequence');
513 $rec->setEnabledSubForms(
514 array(
518 )
519 );
520 $this->form->addItem($rec);
521 }
522
523 // Number of bookings
524 $nu = new ilNumberInputGUI($this->lng->txt('cal_ch_num_bookings'), 'bo');
525 $nu->setSize(2);
526 $nu->setMaxLength(2);
527 $nu->setMinValue(1);
528 $nu->setRequired(true);
529 $this->form->addItem($nu);
530
531 // Deadline
532 $dead = new ilDurationInputGUI($this->lng->txt('cal_ch_deadline'), 'dead');
533 $dead->setInfo($this->lng->txt('cal_ch_deadline_info'));
534 $dead->setShowMinutes(false);
535 $dead->setShowHours(true);
536 $dead->setShowDays(true);
537 $this->form->addItem($dead);
538
539 // Location
540 $lo = new ilTextInputGUI($this->lng->txt('cal_where'), 'lo');
541 $lo->setSize(32);
542 $lo->setMaxLength(128);
543 $this->form->addItem($lo);
544
545 // Description
546 $de = new ilTextAreaInputGUI($this->lng->txt('description'), 'de');
547 $de->setRows(10);
548 $de->setCols(60);
549 $this->form->addItem($de);
550
551 // Target Object
552 $tgt = new ilTextInputGUI($this->lng->txt('cal_ch_target_object'), 'tgt');
553 $tgt->setInfo($this->lng->txt('cal_ch_target_object_info'));
554 $tgt->setSize(16);
555 $tgt->setMaxLength(128);
556 $this->form->addItem($tgt);
557 return $this->form;
558 }
559
563 protected function saveSequence(): void
564 {
565 $this->initFormSequence(self::MODE_CREATE);
566
567 if ($this->form->checkInput()) {
568 $this->form->setValuesByPost();
569
570 $booking = new ilBookingEntry();
571 $booking->setObjId($this->getUserId());
572 $booking->setNumberOfBookings((int) $this->form->getInput('bo'));
573
574 $deadline = $this->form->getInput('dead');
575 $deadline = $deadline['dd'] * 24 + $deadline['hh'];
576 $booking->setDeadlineHours($deadline);
577
578 $tgt = array_map('intval', explode(',', $this->form->getInput('tgt')));
579 $obj_ids = array();
580 foreach ($tgt as $ref_id) {
581 if ($ref_id === 0) {
582 continue;
583 }
585 $type = ilObject::_lookupType($obj_id);
586 $valid_types = array('crs', 'grp');
587 if (!$obj_id or !in_array($type, $valid_types)) {
588 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cal_ch_unknown_repository_object'));
589 $this->tpl->setContent($this->form->getHTML());
590 return;
591 }
592
593 $obj_ids[] = $obj_id;
594 }
595 $booking->setTargetObjIds($obj_ids);
596 $booking->save();
597 $this->createAppointments($booking);
598 $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
599 $this->ctrl->redirect($this, 'appointments');
600 } else {
601 $this->form->setValuesByPost();
602 $this->tpl->setContent($this->form->getHTML());
603 }
604 }
605
610 {
611 $concurrent_dates = new ilDateList(ilDateList::TYPE_DATETIME);
612 $start = clone $this->form->getItemByPostVar('st')->getDate();
613 for ($i = 0; $i < $this->form->getItemByPostVar('ap')->getValue(); $i++) {
614 $concurrent_dates->add(clone $start);
615
616 $start->increment(ilDateTime::MINUTE, $this->form->getItemByPostVar('du')->getMinutes());
617 $start->increment(ilDateTime::HOUR, $this->form->getItemByPostVar('du')->getHours());
618 #$start = new ilDateTime(,IL_CAL_UNIX);
619 }
620
623 $this->getUserId(),
624 $this->lng->txt('cal_ch_personal_ch'),
625 true
626 );
627
628 // Add calendar appointment for each
629
630 $num_appointments = 0;
631 foreach ($concurrent_dates as $dt) {
632 if ($num_appointments >= self::MAX_APPOINTMENTS_PER_SEQUENCE) {
633 break;
634 }
635
636 $end = clone $dt;
637 $end->increment(ilDateTime::MINUTE, $this->form->getItemByPostVar('du')->getMinutes());
638 $end->increment(ilDateTime::HOUR, $this->form->getItemByPostVar('du')->getHours());
639
641 new ilBookingPeriod($dt, $end),
642 $this->form->getItemByPostVar('frequence')->getRecurrence()
643 );
644
645 // Calculate with one year limit
646 $limit = clone $dt;
647 $limit->increment(ilDateTime::YEAR, 1);
648
649 $date_list = $calc->calculateDateList($dt, $limit);
650
651 $num = 0;
652 foreach ($date_list as $app_start) {
653 $app_end = clone $app_start;
654 $app_end->increment(ilDateTime::MINUTE, $this->form->getItemByPostVar('du')->getMinutes());
655 $app_end->increment(ilDateTime::HOUR, $this->form->getItemByPostVar('du')->getHours());
656
657 $entry = new ilCalendarEntry();
658 $entry->setContextId($booking->getId());
659 $entry->setTitle($this->form->getInput('ti'));
660 $entry->setSubtitle("#consultationhour#"); // dynamic, see ilCalendarEntry
661 $entry->setDescription($this->form->getInput('de'));
662 $entry->setLocation($this->form->getInput('lo'));
663 $entry->setStart($app_start);
664 $entry->setEnd($app_end);
665
666 $entry->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
667 $entry->save();
668
669 $cat_assign = new ilCalendarCategoryAssignments($entry->getEntryId());
670 $cat_assign->addAssignment($def_cat->getCategoryID());
671
672 $num_appointments++;
673 }
674 }
675 }
676
677 protected function setTabs(): void
678 {
679 $this->ctrl->setParameter($this, 'user_id', '');
680 $this->tabs->addTab(
681 'consultation_hours_' . $this->user_id,
682 $this->lng->txt('cal_ch_ch'),
683 $this->ctrl->getLinkTarget($this, 'appointments')
684 );
685
687 $this->ctrl->setParameter($this, 'user_id', $user_id);
688 $this->tabs->addTab(
689 'consultation_hours_' . $user_id,
690 $this->lng->txt('cal_ch_ch') . ': ' . $login,
691 $this->ctrl->getLinkTarget($this, 'appointments')
692 );
693 }
694 $this->ctrl->setParameter($this, 'user_id', '');
695 $this->tabs->addTab('ch_settings', $this->lng->txt('settings'), $this->ctrl->getLinkTarget($this, 'settings'));
696 $this->tabs->activateTab('consultation_hours_' . $this->getUserId());
697 }
698
699 public function edit(): void
700 {
701 $apps = $this->initAppointmentIdsFromTableAction();
702 if (!count($apps)) {
703 if ($this->initAppointmentIdsFromPostString() !== []) {
704 $apps = $this->initAppointmentIdsFromPostString();
705 }
706 }
707
708 // first read from hidden input
709 if (!count($apps)) {
710 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
711 $this->appointments();
712 return;
713 }
714
715 $this->initFormSequence(self::MODE_MULTI);
716 $hidden = new ilHiddenInputGUI('apps_string');
717 $hidden->setValue(implode(';', $apps));
718 $this->form->addItem($hidden);
719
720 $first = $apps;
721 $first = array_shift($apps);
722 $entry = new ilCalendarEntry($first);
723
724 $this->form->getItemByPostVar('ti')->setValue($entry->getTitle());
725 $this->form->getItemByPostVar('lo')->setValue($entry->getLocation());
726 $this->form->getItemByPostVar('de')->setValue($entry->getDescription());
727
728 $booking = new ilBookingEntry($entry->getContextId());
729
730 $this->form->getItemByPostVar('bo')->setValue((string) $booking->getNumberOfBookings());
731
732 $ref_ids = array();
733 foreach ($booking->getTargetObjIds() as $obj_id) {
734 $refs = ilObject::_getAllReferences($obj_id);
735 $ref_ids[] = end($refs);
736 }
737 $this->form->getItemByPostVar('tgt')->setValue(implode(',', $ref_ids));
738
739 $deadline = $booking->getDeadlineHours();
740 $this->form->getItemByPostVar('dead')->setDays((int) floor($deadline / 24));
741 $this->form->getItemByPostVar('dead')->setHours($deadline % 24);
742 $this->tpl->setContent($this->form->getHTML());
743 }
744
745 protected function createNewBookingEntry(ilPropertyFormGUI $validate_form): ?ilBookingEntry
746 {
747 $booking = new \ilBookingEntry();
748 $booking->setObjId($this->user_id);
749 $booking->setNumberOfBookings((int) $this->form->getInput('bo'));
750
751 $deadline = $this->form->getInput('dead');
752 $deadline = $deadline['dd'] * 24 + $deadline['hh'];
753 $booking->setDeadlineHours($deadline);
754
755 $tgt = array_map('intval', explode(',', (string) $this->form->getInput('tgt')));
756 $obj_ids = [];
757 foreach ($tgt as $ref_id) {
758 if ($ref_id === 0) {
759 continue;
760 }
762 $type = ilObject::_lookupType($obj_id);
763 $valid_types = ['crs', 'grp'];
764 if (!$obj_id or !in_array($type, $valid_types)) {
765 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cal_ch_unknown_repository_object'));
766 return null;
767 }
768 $obj_ids[] = $obj_id;
769 }
770 $booking->setTargetObjIds($obj_ids);
771 $booking->save();
772 return $booking;
773 }
774
777 array $appointments,
779 ): void {
780 foreach ($appointments as $appointment_id) {
781 $booking_appointment = new \ilCalendarEntry($appointment_id);
782 $booking_start = $booking_appointment->getStart();
783 $booking_end = $booking_appointment->getEnd();
784
785 $deprecatedBooking = \ilBookingEntry::getInstanceByCalendarEntryId($appointment_id);
786 if (!$deprecatedBooking instanceof \ilBookingEntry) {
787 // @todo error handling
788 continue;
789 }
790
792 $deprecatedBooking,
793 $booking_start,
794 $booking_end
795 );
796 foreach ($relevant_appointments as $relevant_appointment_id) {
797 $entry = new \ilCalendarEntry($relevant_appointment_id);
798 $entry->setContextId($booking->getId());
799 $entry->setTitle($form->getInput('ti'));
800 $entry->setLocation($form->getInput('lo'));
801 $entry->setDescription($form->getInput('de'));
802 $entry->update();
803 }
804 }
805 }
806
810 protected function updateMulti(): void
811 {
812 $this->initFormSequence(self::MODE_MULTI);
813 if (!$this->form->checkInput()) {
814 $this->form->setValuesByPost();
815 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
816 $this->edit();
817 return;
818 }
819
820 $this->form->setValuesByPost();
821 $apps = $this->initAppointmentIdsFromPostString();
822
823 // create new booking
824 $booking = $this->createNewBookingEntry($this->form);
825 if (!$booking instanceof \ilBookingEntry) {
826 $this->edit();
827 return;
828 }
829 $this->rewriteBookingIdsForAppointments($booking, $apps, $this->form);
831
832 $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
833 $this->ctrl->redirect($this, 'appointments');
834 $this->tpl->setContent($this->form->getHTML());
835 }
836
840 public function showProfile(): void
841 {
842 $this->tabs->clearTargets();
843
844 $user_id = 0;
845 if ($this->http->wrapper()->query()->has('user')) {
846 $user_id = $this->http->wrapper()->query()->retrieve(
847 'user',
848 $this->refinery->kindlyTo()->int()
849 );
850 }
851 $profile = new PublicProfileGUI($user_id);
852 $profile->setBackUrl($this->getProfileBackUrl());
853 $this->tpl->setContent($this->ctrl->getHTML($profile));
854 }
855
859 protected function getProfileBackUrl(): string
860 {
861 // from repository
862 if ($this->http->wrapper()->query()->has('ref_id')) {
863 $url = $this->ctrl->getLinkTargetByClass('ilCalendarMonthGUI');
864 } // from panel
865 elseif ($this->http->wrapper()->query()->has('panel')) {
866 $url = $this->ctrl->getLinkTargetByClass('ilCalendarPresentationGUI');
867 } // from appointments
868 else {
869 $url = $this->ctrl->getLinkTarget($this, 'appointments');
870 }
871 return $url;
872 }
873
877 public function settings(): void
878 {
879 $this->help->setScreenId("consultation_hours_settings");
880 $this->tabs->activateTab('ch_settings');
881
882 $form = $this->initSettingsForm();
883 $this->tpl->setContent($form->getHTML());
884 }
885
890 {
891 $form = new ilPropertyFormGUI();
892 $form->setFormAction($this->ctrl->getFormAction($this));
893
894 $mng = new ilTextInputGUI($this->lng->txt('cal_ch_manager'), 'mng');
895 $mng->setInfo($this->lng->txt('cal_ch_manager_info'));
896 $form->addItem($mng);
897
898 $mng->setValue(ilConsultationHourAppointments::getManager(true));
899
900 $form->setTitle($this->lng->txt('settings'));
901 $form->addCommandButton('updateSettings', $this->lng->txt('save'));
902 return $form;
903 }
904
908 public function updateSettings(): void
909 {
910 $form = $this->initSettingsForm();
911 if ($form->checkInput()) {
912 $mng = $form->getInput('mng');
914 $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
915 $this->ctrl->redirect($this, 'settings');
916 } else {
917 $this->tabs->activateTab('ch_settings');
918
919 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cal_ch_unknown_user'));
920 $field = $form->getItemByPostVar('mng');
921 $field->setValue($mng);
922 $this->tpl->setContent($form->getHTML());
923 return;
924 }
925 }
926 }
927
928 protected function appointments(): void
929 {
930 $this->initViewMode();
931 $table = new BookingTableGUI(
932 new BookingDataProvider($this->getUserId(), $this->vm_period, $this->vm_status)
933 );
934 $this->tpl->setContent(
935 $this->renderViewControl() .
936 $table->render()
937 );
938 }
939
940
941 protected function handleBookingTableActions(): void
942 {
943 $action = $this->http->wrapper()->query()->retrieve(
944 BookingTableGUI::ACTION_TOKEN_NS,
945 $this->refinery->byTrying(
946 [
947 $this->refinery->kindlyTo()->string(),
948 $this->refinery->always('')
949 ]
950 )
951 );
952 match ($action) {
953 'edit' => $this->edit(),
954 'searchUsersForAppointments' => $this->searchUsersForAppointments(),
955 'confirmDeleteAppointments' => $this->confirmDeleteAppointments(),
956 'confirmCancelBooking' => $this->confirmCancelBooking(true),
957 'confirmDeleteBooking' => $this->confirmCancelBooking(false),
958 'sendMail' => $this->sendMailToSelectedUsers(),
959 default => $this->ctrl->redirect($this, 'appointments')
960 };
961 }
962
963 protected function sendMailToSelectedUsers(): void
964 {
965 $appointment_ids = $this->initAppointmentIdsFromTableAction();
966 if ($appointment_ids === []) {
967 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
968 $this->appointments();
969 return;
970 }
971
972 $bookusers = [];
973 foreach ($appointment_ids as $appointment_id) {
974 $entry = new ilCalendarEntry($appointment_id);
975 $booking = new ilBookingEntry($entry->getContextId());
976 foreach ($booking->getCurrentBookings($entry->getEntryId()) as $bookuser) {
977 $login = ilObjUser::_lookupLogin($bookuser);
978 if (!in_array($login, $bookusers)) {
979 $bookusers[] = $login;
980 }
981 }
982 }
983 $this->ctrl->redirectToURL(
985 $this,
986 'appointments',
987 [],
988 [
989 'type' => 'new',
990 'rcp_to' => implode(',', $bookusers)
991 ]
992 )
993 );
994 }
995
996 protected function confirmCancelBooking(bool $with_notification = true): void
997 {
998 $appointment_ids = $this->initAppointmentIdsFromTableAction();
999 if ($appointment_ids === []) {
1000 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1001 $this->appointments();
1002 return;
1003 }
1004
1005 $appointment = end($appointment_ids);
1006 $this->ctrl->setParameter($this, 'appointment_id', $appointment);
1007 $entry = new ilCalendarEntry($appointment);
1008 $booking = new ilBookingEntry($entry->getContextId());
1009
1010 $cancel = new \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI(
1011 $this,
1012 $entry,
1013 $booking,
1014 $with_notification ?
1015 \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_CANCEL :
1016 \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_DELETE
1017 );
1018 $modal = $cancel->renderModal();
1019 $output = $this->ui_renderer->renderAsync($modal);
1020 $this->http->saveResponse($this->http->response()->withBody(
1021 Streams::ofString($output)
1022 ));
1023 $this->http->sendResponse();
1024 $this->http->close();
1025 }
1026
1027 protected function deleteBooking(): void
1028 {
1029 $this->cancelBooking(false);
1030 }
1031
1032 protected function cancelBooking(bool $with_notification = true): void
1033 {
1034 $appointment_id = $this->http->wrapper()->query()->retrieve(
1035 'appointment_id',
1036 $this->refinery->byTrying(
1037 [
1038 $this->refinery->kindlyTo()->int(),
1039 $this->refinery->always(0)
1040 ]
1041 )
1042 );
1043 if (!$appointment_id) {
1044 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1045 $this->appointments();
1046 return;
1047 }
1048
1049 $entry = new ilCalendarEntry($appointment_id);
1050 $booking = new ilBookingEntry($entry->getContextId());
1051 $cancel = new \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI(
1052 $this,
1053 $entry,
1054 $booking,
1055 $with_notification ?
1056 \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_CANCEL :
1057 \ILIAS\Calendar\ConsultationHours\BookingCancellationGUI::TYPE_DELETE
1058 );
1059 $data = $cancel->renderModal()->withRequest($this->http->request())->getData();
1060 foreach ((array) $data['bookings'] as $user => $checked) {
1061 if ($checked) {
1063 $user,
1064 $appointment_id,
1065 $with_notification
1066 );
1067 }
1068 }
1069 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cal_ch_canceled_bookings'), true);
1070 $this->ctrl->redirect($this, 'appointments');
1071 }
1072
1073 protected function confirmDeleteAppointments(): void
1074 {
1075 $appointment_ids = $this->initAppointmentIdsFromTableAction();
1076 if (!count($appointment_ids)) {
1077 $output = $this->ui_factory->messageBox()->failure($this->lng->txt('select_one'));
1078 } else {
1079 $items = [];
1080 foreach ($appointment_ids as $appointment) {
1081 $entry = new ilCalendarEntry($appointment);
1082 $items[] = $this->ui_factory->modal()->interruptiveItem()->standard(
1083 (string) $appointment,
1084 ilDatePresentation::formatDate($entry->getStart()) . ', ' . $entry->getTitle()
1085 );
1086 }
1087
1088 $output = $this->ui_factory->modal()->interruptive(
1089 $this->lng->txt('confirm'),
1090 $this->lng->txt('cal_ch_delete_app_booking_info'),
1091 $this->ctrl->getFormAction($this, 'deleteAppointments')
1092 )->withAffectedItems($items);
1093 }
1094
1095 $rendered_output = $this->ui_renderer->renderAsync($output);
1096 $this->http->saveResponse($this->http->response()->withBody(
1097 Streams::ofString($rendered_output)
1098 ));
1099 $this->http->sendResponse();
1100 $this->http->close();
1101 }
1102
1103 protected function deleteAppointments(): void
1104 {
1105 $appointment_ids = $this->http->wrapper()->post()->retrieve(
1106 'interruptive_items',
1107 $this->refinery->byTrying(
1108 [
1109 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
1110 $this->refinery->always([])
1111 ]
1112 )
1113 );
1114 if (!count($appointment_ids)) {
1115 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1116 $this->appointments();
1117 return;
1118 }
1119
1120 foreach ($appointment_ids as $appointment_id) {
1121 // cancel booking for users
1122 $booking = ilBookingEntry::getInstanceByCalendarEntryId($appointment_id);
1123 if ($booking) {
1124 foreach ($booking->getCurrentBookings($appointment_id) as $user_id) {
1125 ilConsultationHourUtils::cancelBooking($user_id, $appointment_id, false);
1126 }
1127 }
1128 // remove calendar entries
1129 $entry = new ilCalendarEntry($appointment_id);
1130 $entry->delete();
1132 }
1134 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cal_deleted_app'), true);
1135 $this->ctrl->redirect($this, 'appointments');
1136 }
1137
1139 {
1140 $add_sequence_button = $this->ui_factory->button()->standard(
1141 $this->lng->txt('cal_ch_add_sequence'),
1142 $this->ctrl->getLinkTarget($this, 'createSequence')
1143 );
1144 return $add_sequence_button;
1145 }
1146
1147 protected function renderViewControl(): string
1148 {
1149 $toolbar = new ilToolbarGUI();
1150 $toolbar->addComponent($this->initSequenceCreation());
1151 $toolbar->addSeparator();
1152
1153 $this->ctrl->setParameter($this, 'vm_period', self::VIEW_MODE_PERIOD_PAST);
1154 $actions[$this->lng->txt('cal_ch_vm_period_' . self::VIEW_MODE_PERIOD_PAST)] = $this->ctrl->getLinkTarget(
1155 $this,
1156 'appointments'
1157 );
1158 $this->ctrl->setParameter($this, 'vm_period', self::VIEW_MODE_PERIOD_UPCOMING);
1159 $actions[$this->lng->txt('cal_ch_vm_period_' . self::VIEW_MODE_PERIOD_UPCOMING)] = $this->ctrl->getLinkTarget(
1160 $this,
1161 'appointments'
1162 );
1163 $this->ctrl->setParameter($this, 'vm_period', self::VIEW_MODE_PERIOD_ALL);
1164 $actions[$this->lng->txt('cal_ch_vm_period_' . self::VIEW_MODE_PERIOD_ALL)] = $this->ctrl->getLinkTarget(
1165 $this,
1166 'appointments'
1167 );
1168 $this->ctrl->setParameter($this, 'vm_period', '');
1169
1170 $view_control_period = $this->ui_factory->viewControl()->mode(
1171 $actions,
1172 $this->lng->txt('meta_aria_language_selection')
1173 )->withActive($this->lng->txt('cal_ch_vm_period_' . $this->vm_period));
1174
1175 $toolbar->addComponent($view_control_period);
1176
1177 $actions = [];
1178 $this->ctrl->setParameter($this, 'vm_status', self::VIEW_MODE_STATUS_OPEN);
1179 $actions[$this->lng->txt('cal_ch_vm_status_' . self::VIEW_MODE_STATUS_OPEN)] = $this->ctrl->getLinkTarget(
1180 $this,
1181 'appointments'
1182 );
1183 $this->ctrl->setParameter($this, 'vm_status', self::VIEW_MODE_STATUS_BOOKED);
1184 $actions[$this->lng->txt('cal_ch_vm_status_' . self::VIEW_MODE_STATUS_BOOKED)] = $this->ctrl->getLinkTarget(
1185 $this,
1186 'appointments'
1187 );
1188 $this->ctrl->setParameter($this, 'vm_status', self::VIEW_MODE_STATUS_ALL);
1189 $actions[$this->lng->txt('cal_ch_vm_status_' . self::VIEW_MODE_STATUS_ALL)] = $this->ctrl->getLinkTarget(
1190 $this,
1191 'appointments'
1192 );
1193 $this->ctrl->setParameter($this, 'vm_status', '');
1194
1195 $view_control_status = $this->ui_factory->viewControl()->mode(
1196 $actions,
1197 $this->lng->txt('meta_aria_language_selection')
1198 )->withActive($this->lng->txt('cal_ch_vm_status_' . $this->vm_status));
1199
1200 $toolbar->addComponent($view_control_status);
1201 return $toolbar->getHTML();
1202 }
1203
1204 protected function initViewMode(): void
1205 {
1206 global $DIC;
1207
1208 $user = $DIC->user();
1209 $vm_period = $this->http->wrapper()->query()->retrieve(
1210 'vm_period',
1211 $this->refinery->byTrying(
1212 [
1213 $this->refinery->kindlyTo()->string(),
1214 $this->refinery->always('')
1215 ]
1216 )
1217 );
1218 $vm_status = $this->http->wrapper()->query()->retrieve(
1219 'vm_status',
1220 $this->refinery->byTrying(
1221 [
1222 $this->refinery->kindlyTo()->string(),
1223 $this->refinery->always('')
1224 ]
1225 )
1226 );
1227
1228 if ($vm_period !== '') {
1229 $user->writePref('cal_ch_vm_period', $vm_period);
1230 }
1231 if ($vm_status !== '') {
1232 $user->writePref('cal_ch_vm_status', $vm_status);
1233 }
1234 $this->vm_period = $user->getPref('cal_ch_vm_period') ? $user->getPref('cal_ch_vm_period') : self::VIEW_MODE_PERIOD_ALL;
1235 $this->vm_status = $user->getPref('cal_ch_vm_status') ? $user->getPref('cal_ch_vm_status') : self::VIEW_MODE_STATUS_ALL;
1236
1237 }
1238
1239}
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:
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(?array $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