ILIAS  release_8 Revision v8.24
class.ilBookingProcessGUI.php
Go to the documentation of this file.
1<?php
2
24{
25 protected array $raw_post_data;
26 protected \ILIAS\BookingManager\StandardGUIRequest $book_request;
28 protected int $booking_object_id;
29 protected int $user_id_to_book;
30 protected int $user_id_assigner;
31 protected string $seed;
32 protected string $sseed;
34 protected int $context_obj_id;
35 protected ilCtrl $ctrl;
37 protected ilLanguage $lng;
40 protected ilObjUser $user;
41 protected int $book_obj_id;
42 protected array $rsv_ids = [];
43
44 public function __construct(
48 string $seed = "",
49 string $sseed = "",
50 int $context_obj_id = 0
51 ) {
53 global $DIC;
54
55 $this->ctrl = $DIC->ctrl();
56 $this->tpl = $DIC["tpl"];
57 $this->lng = $DIC->language();
58 $this->access = $DIC->access();
59 $this->tabs_gui = $DIC->tabs();
60 $this->user = $DIC->user();
61 $this->help = $help;
62
63 $this->context_obj_id = $context_obj_id;
64
65 $this->book_obj_id = $booking_object_id;
66
67 $this->pool = $pool;
68
69 $this->seed = $seed;
70 $this->sseed = $sseed;
71 $this->book_request = $DIC->bookingManager()
72 ->internal()
73 ->gui()
74 ->standardRequest();
75
76 $this->rsv_ids = $this->book_request->getReservationIdsFromString();
77
78 $this->raw_post_data = $DIC->http()->request()->getParsedBody();
79
80 $this->user_id_assigner = $this->user->getId();
81 if ($this->book_request->getBookedUser() > 0) {
82 $this->user_id_to_book = $this->book_request->getBookedUser();
83 } else {
84 $this->user_id_to_book = $this->user_id_assigner; // by default user books his own booking objects.
85 }
86 $this->ctrl->saveParameter($this, ["bkusr"]);
87 }
88
89 public function executeCommand(): void
90 {
92
93 $next_class = $ctrl->getNextClass($this);
94 $cmd = $ctrl->getCmd("show");
95 switch ($next_class) {
96 default:
97 if (in_array($cmd, array("book", "back",
98 "assignParticipants",
99 "bookMultipleParticipants",
100 "saveMultipleBookings",
101 "confirmedBooking",
102 "confirmBookingNumbers",
103 "confirmedBookingNumbers",
104 "displayPostInfo",
105 "deliverPostFile"
106 ))) {
107 $this->$cmd();
108 }
109 }
110 }
111
112 // Back to parent
113 protected function back(): void
114 {
115 $this->ctrl->returnToParent($this);
116 }
117
118 protected function setHelpId(string $a_id): void
119 {
120 $this->help->setHelpId($a_id);
121 }
122
123 protected function checkPermissionBool(string $a_perm): bool
124 {
125 $ilAccess = $this->access;
126
127 if (!$ilAccess->checkAccess($a_perm, "", $this->pool->getRefId())) {
128 return false;
129 }
130 return true;
131 }
132
133 protected function checkPermission(string $a_perm): void
134 {
135 if (!$this->checkPermissionBool($a_perm)) {
136 $this->tpl->setOnScreenMessage('failure', $this->lng->txt("no_permission"), true);
137 $this->back();
138 }
139 }
140
141 //
142 // Step 1
143 //
144
145
149 public function book(): void // ok
150 {
152
153 $this->tabs_gui->clearTargets();
154 $this->tabs_gui->setBackTarget($this->lng->txt('book_back_to_list'), $this->ctrl->getLinkTarget($this, 'back'));
155
156 $this->setHelpId("book");
157
158 $obj = new ilBookingObject($this->book_obj_id);
159
160 $this->lng->loadLanguageModule("dateplaner");
161 $this->ctrl->setParameter($this, 'object_id', $obj->getId());
162
163 if ($this->user_id_to_book !== $this->user_id_assigner) {
164 $this->ctrl->setParameter($this, 'bkusr', $this->user_id_to_book);
165 }
166
167 if ($this->pool->getScheduleType() === ilObjBookingPool::TYPE_FIX_SCHEDULE) {
168 $schedule = new ilBookingSchedule($obj->getScheduleId());
169
170 $tpl->setContent($this->renderSlots($schedule, array($obj->getId()), $obj->getTitle()));
171 } else {
172 $cgui = new ilConfirmationGUI();
173 $cgui->setHeaderText($this->lng->txt("book_confirm_booking_no_schedule"));
174
175 $cgui->setFormAction($this->ctrl->getFormAction($this));
176 $cgui->setCancel($this->lng->txt("cancel"), "back");
177 $cgui->setConfirm($this->lng->txt("confirm"), "confirmedBooking");
178
179 $cgui->addItem("object_id", $obj->getId(), $obj->getTitle());
180
181 $tpl->setContent($cgui->getHTML());
182 }
183 }
184
185 protected function renderSlots(
186 ilBookingSchedule $schedule,
187 array $object_ids,
188 string $title
189 ): string {
190 $ilUser = $this->user;
191
192 // fix
193 if (!$schedule->getRaster()) {
194 $mytpl = new ilTemplate('tpl.booking_reservation_fix.html', true, true, 'Modules/BookingManager');
195
196 $mytpl->setVariable('FORM_ACTION', $this->ctrl->getFormAction($this));
197 $mytpl->setVariable('TXT_TITLE', $this->lng->txt('book_reservation_title'));
198 $mytpl->setVariable('TXT_INFO', $this->lng->txt('book_reservation_fix_info'));
199 $mytpl->setVariable('TXT_OBJECT', $title);
200 $mytpl->setVariable('TXT_CMD_BOOK', $this->lng->txt('book_confirm_booking'));
201 $mytpl->setVariable('TXT_CMD_CANCEL', $this->lng->txt('cancel'));
202
203 $user_settings = ilCalendarUserSettings::_getInstanceByUserId($ilUser->getId());
204
205 $morning_aggr = $user_settings->getDayStart();
206 $evening_aggr = $user_settings->getDayEnd();
207 $hours = array();
208 for ($i = $morning_aggr;$i <= $evening_aggr;$i++) {
209 $hours[$i] = "";
210 switch ($user_settings->getTimeFormat()) {
212 if ($morning_aggr > 0 && $i === $morning_aggr) {
213 $hours[$i] = sprintf('%02d:00', 0) . "-";
214 }
215 $hours[$i] .= sprintf('%02d:00', $i);
216 if ($evening_aggr < 23 && $i === $evening_aggr) {
217 $hours[$i] .= "-" . sprintf('%02d:00', 23);
218 }
219 break;
220
222 if ($morning_aggr > 0 && $i === $morning_aggr) {
223 $hours[$i] = date('h a', mktime(0, 0, 0, 1, 1, 2000)) . "-";
224 }
225 $hours[$i] .= date('h a', mktime($i, 0, 0, 1, 1, 2000));
226 if ($evening_aggr < 23 && $i === $evening_aggr) {
227 $hours[$i] .= "-" . date('h a', mktime(23, 0, 0, 1, 1, 2000));
228 }
229 break;
230 }
231 }
232
233 if ($this->seed !== "") {
234 $find_first_open = false;
235 $seed = new ilDate($this->seed, IL_CAL_DATE);
236 } else {
237 $find_first_open = true;
238 $seed = ($this->sseed !== "")
239 ? new ilDate($this->sseed, IL_CAL_DATE)
240 : new ilDate(time(), IL_CAL_UNIX);
241 }
242
243 $week_start = $user_settings->getWeekStart();
244
245 $dates = array();
246 if (!$find_first_open) {
247 $this->buildDatesBySchedule($week_start, $hours, $schedule, $object_ids, $seed, $dates);
248 } else {
249
250 //loop for 1 week
251 $has_open_slot = $this->buildDatesBySchedule($week_start, $hours, $schedule, $object_ids, $seed, $dates);
252
253 // find first open slot
254 if (!$has_open_slot) {
255 // 1 year is limit for search
256 $limit = clone($seed);
257 $limit->increment(ilDateTime::YEAR, 1);
258 $limit = $limit->get(IL_CAL_UNIX);
259
260 while (!$has_open_slot && $seed->get(IL_CAL_UNIX) < $limit) {
261 $seed->increment(ilDateTime::WEEK, 1);
262
263 $dates = array();
264 $has_open_slot = $this->buildDatesBySchedule($week_start, $hours, $schedule, $object_ids, $seed, $dates);
265 }
266 }
267 }
268
269 $navigation = new ilCalendarHeaderNavigationGUI($this, $seed, ilDateTime::WEEK, 'book');
270 $mytpl->setVariable('NAVIGATION', $navigation->getHTML());
271
273 foreach (ilCalendarUtil::_buildWeekDayList($seed, $week_start)->get() as $date) {
274 $date_info = $date->get(IL_CAL_FKT_GETDATE, '', 'UTC');
275
276 $mytpl->setCurrentBlock('weekdays');
277 $mytpl->setVariable('TXT_WEEKDAY', ilCalendarUtil::_numericDayToString((int) $date_info['wday']));
278 $mytpl->setVariable('TXT_DATE', $date_info['mday'] . ' ' . ilCalendarUtil::_numericMonthToString($date_info['mon']));
279 $mytpl->parseCurrentBlock();
280 }
281
282 $color = array();
284 for ($loop = 0; $loop < 7; $loop++) {
285 $col = $all[$loop];
287 $color[$loop + 1] = 'border-bottom: 1px solid ' . $col . '; background-color: ' . $col . '; color: ' . $fnt;
288 }
289
290 $counter = 0;
291 foreach ($dates as $hour => $days) {
292 $caption = $days;
293 $caption = array_shift($caption);
294
295 for ($loop = 1; $loop < 8; $loop++) {
296 if (!isset($days[$loop])) {
297 $mytpl->setCurrentBlock('dates');
298 $mytpl->setVariable('DUMMY', '&nbsp;');
299 } elseif (isset($days[$loop]['captions'])) {
300 foreach ($days[$loop]['captions'] as $slot_id => $slot_caption) {
301 $mytpl->setCurrentBlock('choice');
302 $mytpl->setVariable('TXT_DATE', $slot_caption);
303 $mytpl->setVariable('VALUE_DATE', $slot_id);
304 $mytpl->setVariable('DATE_COLOR', $color[$loop]);
305 $mytpl->setVariable(
306 'TXT_AVAILABLE',
307 sprintf(
308 $this->lng->txt('book_reservation_available'),
309 $days[$loop]['available'][$slot_id]
310 )
311 );
312 $mytpl->parseCurrentBlock();
313 }
314
315 $mytpl->setCurrentBlock('dates');
316 $mytpl->setVariable('DUMMY', '');
317 } elseif (isset($days[$loop]['in_slot'])) {
318 $mytpl->setCurrentBlock('dates');
319 $mytpl->setVariable('DATE_COLOR', $color[$loop]);
320 } else {
321 $mytpl->setCurrentBlock('dates');
322 $mytpl->setVariable('DUMMY', '&nbsp;');
323 }
324 $mytpl->parseCurrentBlock();
325 }
326
327 $mytpl->setCurrentBlock('slots');
328 $mytpl->setVariable('TXT_HOUR', $caption);
329 if ($counter % 2) {
330 $mytpl->setVariable('CSS_ROW', 'tblrow1');
331 } else {
332 $mytpl->setVariable('CSS_ROW', 'tblrow2');
333 }
334 $mytpl->parseCurrentBlock();
335
336 $counter++;
337 }
338 return $mytpl->get();
339 }
340
341 return "";
342 }
343
344 protected function buildDatesBySchedule(
345 int $week_start,
346 array $hours,
347 ilBookingSchedule $schedule,
348 array $object_ids,
349 ilDate $seed,
350 array &$dates
351 ): bool {
352 $ilUser = $this->user;
353
354 $user_settings = ilCalendarUserSettings::_getInstanceByUserId($ilUser->getId());
355
356 $map = array('mo', 'tu', 'we', 'th', 'fr', 'sa', 'su');
357 $definition = $schedule->getDefinition();
358
359 $av_from = ($schedule->getAvailabilityFrom() && !$schedule->getAvailabilityFrom()->isNull())
360 ? $schedule->getAvailabilityFrom()->get(IL_CAL_DATE)
361 : null;
362 $av_to = ($schedule->getAvailabilityTo() && !$schedule->getAvailabilityTo()->isNull())
363 ? $schedule->getAvailabilityTo()->get(IL_CAL_DATE)
364 : null;
365
366 $has_open_slot = false;
368 foreach (ilCalendarUtil::_buildWeekDayList($seed, $week_start)->get() as $date) {
369 $date_info = $date->get(IL_CAL_FKT_GETDATE, '', 'UTC');
370
371 #24045 and #24936
372 if ($av_from || $av_to) {
373 $today = $date->get(IL_CAL_DATE);
374
375 if ($av_from && $av_from > $today) {
376 continue;
377 }
378
379 if ($av_to && $av_to < $today) {
380 continue;
381 }
382 }
383
384 $slots = array();
385 if (isset($definition[$map[$date_info['isoday'] - 1]])) {
386 $slots = array();
387 foreach ($definition[$map[$date_info['isoday'] - 1]] as $slot) {
388 $slot = explode('-', $slot);
389 $slots[] = array('from' => str_replace(':', '', $slot[0]),
390 'to' => str_replace(':', '', $slot[1]));
391 }
392 }
393
394 $slot_captions = array();
395 foreach ($hours as $hour => $period) {
396 $dates[$hour][0] = $period;
397
398 $period = explode("-", $period);
399
400 // #13738
401 if ($user_settings->getTimeFormat() === ilCalendarSettings::TIME_FORMAT_12) {
402 $period[0] = date("H", strtotime($period[0]));
403 if (count($period) === 2) {
404 $period[1] = date("H", strtotime($period[1]));
405 }
406 }
407
408 $period_from = (int) substr($period[0], 0, 2) . "00";
409 if (count($period) === 1) {
410 $period_to = (int) substr($period[0], 0, 2) . "59";
411 } else {
412 $period_to = (int) substr($period[1], 0, 2) . "59";
413 }
414
415 $column = $date_info['isoday'];
416 if (!$week_start) {
417 if ($column < 7) {
418 $column++;
419 } else {
420 $column = 1;
421 }
422 }
423
424 if (count($slots)) {
425 $in = false;
426 foreach ($slots as $slot) {
427 $slot_from = mktime(substr($slot['from'], 0, 2), substr($slot['from'], 2, 2), 0, $date_info["mon"], $date_info["mday"], $date_info["year"]);
428 $slot_to = mktime(substr($slot['to'], 0, 2), substr($slot['to'], 2, 2), 0, $date_info["mon"], $date_info["mday"], $date_info["year"]);
429
430 // always single object, we can sum up
431 $nr_available = ilBookingReservation::getAvailableObject($object_ids, $slot_from, $slot_to - 1, false, true);
432
433 // any objects available?
434 if (!array_sum($nr_available)) {
435 continue;
436 }
437
438 // check deadline
439 if ($schedule->getDeadline() >= 0) {
440 // 0-n hours before slots begins
441 if ($slot_from < (time() + $schedule->getDeadline() * 60 * 60)) {
442 continue;
443 }
444 } elseif ($slot_to < time()) {
445 continue;
446 }
447
448 // is slot active in current hour?
449 if ((int) $slot['from'] < $period_to && (int) $slot['to'] > $period_from) {
450 $from = ilDatePresentation::formatDate(new ilDateTime($slot_from, IL_CAL_UNIX));
451 $from_a = explode(' ', $from);
452 $from = array_pop($from_a);
454 $to_a = explode(' ', $to);
455 $to = array_pop($to_a);
456
457 // show caption (first hour) of slot
458 $id = $slot_from . '_' . $slot_to;
459 if (!in_array($id, $slot_captions)) {
460 $dates[$hour][$column]['captions'][$id] = $from . '-' . $to;
461 $dates[$hour][$column]['available'][$id] = array_sum($nr_available);
462 $slot_captions[] = $id;
463 }
464
465 $in = true;
466 }
467 }
468 // (any) active slot
469 if ($in) {
470 $has_open_slot = true;
471 $dates[$hour][$column]['in_slot'] = true;
472 }
473 }
474 }
475 }
476
477 return $has_open_slot;
478 }
479
480 //
481 // Step 1a)
482 //
483 // Assign multiple participants (starting from participants screen) (no, from object screen!)
484 //
485
486 // Table to assign participants to an object.
487 public function assignParticipants(): void
488 {
489 $this->tabs_gui->clearTargets();
490 $this->tabs_gui->setBackTarget($this->lng->txt('book_back_to_list'), $this->ctrl->getLinkTarget($this, 'back'));
491
492 $table = new ilBookingAssignParticipantsTableGUI($this, 'assignParticipants', $this->pool->getRefId(), $this->pool->getId(), $this->book_obj_id);
493
494 $this->tpl->setContent($table->getHTML());
495 }
496
500 public function bookMultipleParticipants(): void
501 {
502 $participants = $this->book_request->getParticipants();
503 if (count($participants) === 0) {
504 $this->back();
505 return;
506 }
507
508 $this->tabs_gui->clearTargets();
509 $this->tabs_gui->setBackTarget($this->lng->txt("back"), $this->ctrl->getLinkTarget($this, 'assignparticipants'));
510
511 $conf = new ilConfirmationGUI();
512 $conf->setFormAction($this->ctrl->getFormAction($this));
513
514 //add user list as items.
515 foreach ($participants as $id) {
517 $conf->addItem("participants[]", $id, $name);
518 }
519
520 $available = ilBookingReservation::numAvailableFromObjectNoSchedule($this->book_obj_id);
521 if (count($participants) > $available) {
522 $obj = new ilBookingObject($this->book_obj_id);
523 $conf->setHeaderText(
524 sprintf(
525 $this->lng->txt('book_limit_objects_available'),
526 count($participants),
527 $obj->getTitle(),
528 $available
529 )
530 );
531 } else {
532 $conf->setHeaderText($this->lng->txt('book_confirm_booking_no_schedule'));
533 $conf->addHiddenItem("object_id", $this->book_obj_id);
534 $conf->setConfirm($this->lng->txt("assign"), "saveMultipleBookings");
535 }
536
537 $conf->setCancel($this->lng->txt("cancel"), 'redirectToList');
538 $this->tpl->setContent($conf->getHTML());
539 }
540
541 public function redirectToList(): void
542 {
543 $this->ctrl->redirect($this, 'assignParticipants');
544 }
545
550 public function saveMultipleBookings(): void
551 {
552 $participants = $this->book_request->getParticipants();
553 $object_id = $this->book_request->getObjectId();
554 if (count($participants) > 0 && $object_id > 0) {
555 $this->book_obj_id = $object_id;
556 } else {
557 $this->back();
558 }
559 $rsv_ids = array();
560 foreach ($participants as $id) {
561 $this->user_id_to_book = $id;
562 $rsv_ids[] = $this->processBooking($this->book_obj_id);
563 }
564
565 if (count($rsv_ids)) {
566 $this->tpl->setOnScreenMessage('success', "booking_multiple_succesfully");
567 } else {
568 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('book_reservation_failed_overbooked'), true);
569 }
570 $this->back();
571 }
572
573
574 //
575 // Step 2: Confirmation
576 //
577
578 // Book object - either of type or specific - for given dates
579 public function confirmedBooking(): bool
580 {
581 $success = false;
582 $rsv_ids = array();
583
584 if ($this->pool->getScheduleType() !== ilObjBookingPool::TYPE_FIX_SCHEDULE) {
585 if ($this->book_obj_id > 0) {
586 $object_id = $this->book_obj_id;
587 if ($object_id) {
589 count(ilBookingReservation::getObjectReservationForUser($object_id, $this->user_id_to_book)) === 0) { // #18304
590 $rsv_ids[] = $this->processBooking($object_id);
591 $success = $object_id;
592 } else {
593 // #11852
594 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('book_reservation_failed_overbooked'), true);
595 $this->ctrl->redirect($this, 'back');
596 }
597 }
598 }
599 } else {
600 $dates = $this->book_request->getDates();
601 if (count($dates) === 0) {
602 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
603 $this->book();
604 return false;
605 }
606
607 // single object reservation(s)
608 if ($this->book_obj_id > 0) {
609 $confirm = array();
610
611 $object_id = $this->book_obj_id;
612 $group_id = null;
613 if ($object_id) {
614 $nr = ilBookingObject::getNrOfItemsForObjects(array($object_id));
615 // needed for recurrence
617 $repo = $f->getRepo();
618 $group_id = $repo->getNewGroupId();
619 foreach ($dates as $date) {
620 $fromto = explode('_', $date);
621 $from = (int) $fromto[0];
622 $to = (int) $fromto[1] - 1;
623
624 $counter = ilBookingReservation::getAvailableObject(array($object_id), $from, $to, false, true);
625 $counter = $counter[$object_id];
626 if ($counter) {
627 // needed for recurrence
628 $confirm[$object_id . "_" . $from . "_" . ($to + 1)] = $counter;
629 }
630 }
631 }
632
633 if (count($confirm)) {
634 $this->confirmBookingNumbers($confirm, $group_id);
635 return false;
636 }
637 }
638 }
639
640 if ($success) {
641 $this->saveParticipant();
642 $this->handleBookingSuccess($success, $rsv_ids);
643 } else {
644 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('book_reservation_failed'), true);
645 $this->ctrl->redirect($this, 'book');
646 }
647 return true;
648 }
649
653 protected function saveParticipant(): void
654 {
655 $participant = new ilBookingParticipant($this->user_id_to_book, $this->pool->getId());
656 }
657
663 public function processBooking(
664 int $a_object_id,
665 int $a_from = null,
666 int $a_to = null,
667 int $a_group_id = null
668 ): int {
669 // #11995
670 $this->checkPermission('read');
671
672 $reservation = new ilBookingReservation();
673 $reservation->setObjectId($a_object_id);
674 $reservation->setUserId($this->user_id_to_book);
675 $reservation->setAssignerId($this->user_id_assigner);
676 $reservation->setFrom((int) $a_from);
677 $reservation->setTo((int) $a_to);
678 $reservation->setGroupId((int) $a_group_id);
679 $reservation->setContextObjId($this->context_obj_id);
680 $reservation->save();
681
682 if ($a_from) {
683 $this->lng->loadLanguageModule('dateplaner');
684 $def_cat = ilCalendarUtil::initDefaultCalendarByType(ilCalendarCategory::TYPE_BOOK, $this->user_id_to_book, $this->lng->txt('cal_ch_personal_book'), true);
685
686 $object = new ilBookingObject($a_object_id);
687
688 $entry = new ilCalendarEntry();
689 $entry->setStart(new ilDateTime($a_from, IL_CAL_UNIX));
690 $entry->setEnd(new ilDateTime($a_to, IL_CAL_UNIX));
691 $entry->setTitle($this->lng->txt('book_cal_entry') . ' ' . $object->getTitle());
692 $entry->setContextId($reservation->getId());
693 $entry->save();
694
695 $assignment = new ilCalendarCategoryAssignments($entry->getEntryId());
696 if ($def_cat !== null) {
697 $assignment->addAssignment($def_cat->getCategoryID());
698 }
699 }
700
701 return $reservation->getId();
702 }
703
704 //
705 // Confirm booking numbers
706 //
707
708 public function confirmBookingNumbers(
709 array $a_objects_counter,
710 int $a_group_id,
711 ilPropertyFormGUI $a_form = null
712 ): void {
713 $tpl = $this->tpl;
714
715 $this->tabs_gui->clearTargets();
716 $this->tabs_gui->setBackTarget($this->lng->txt('book_back_to_list'), $this->ctrl->getLinkTarget($this, 'back'));
717
718 if (!$a_form) {
719 $a_form = $this->initBookingNumbersForm($a_objects_counter, $a_group_id);
720 }
721
722 $tpl->setContent($a_form->getHTML());
723 }
724
729 protected function initBookingNumbersForm(
730 array $a_objects_counter,
731 int $a_group_id,
732 bool $a_reload = false,
733 ?array $new_values = null
735 $form = new ilPropertyFormGUI();
736 $form->setFormAction($this->ctrl->getFormAction($this, "confirmedBooking"));
737 $form->setTitle($this->lng->txt("book_confirm_booking_schedule_number_of_objects"));
738 $form->setDescription($this->lng->txt("book_confirm_booking_schedule_number_of_objects_info"));
739
740 $section = false;
741 $min_date = null;
742 foreach ($a_objects_counter as $id => $counter) {
743 $id = explode("_", $id);
744 $book_id = $id[0] . "_" . $id[1] . "_" . $id[2] . "_" . $counter;
745
746 $obj = new ilBookingObject($id[0]);
747
748 if (!$section) {
749 $section = new ilFormSectionHeaderGUI();
750 $section->setTitle($obj->getTitle());
751 $form->addItem($section);
752
753 $section = true;
754 }
755
756 $period = /* $this->lng->txt("book_period").": ". */
758 new ilDateTime($id[1], IL_CAL_UNIX),
759 new ilDateTime($id[2], IL_CAL_UNIX)
760 );
761
762 $nr_field = new ilNumberInputGUI($period, "conf_nr__" . $book_id);
763 $nr_field->setValue(1);
764 $nr_field->setSize(3);
765 $nr_field->setMaxValue($counter);
766 $nr_field->setMinValue($counter ? 1 : 0);
767 $nr_field->setRequired(true);
768 if (!is_null($new_values) && isset($new_values["conf_nr__" . $book_id])) {
769 $nr_field->setRequestParam(
770 "conf_nr__" . $book_id,
771 $new_values["conf_nr__" . $book_id]
772 );
773 }
774 $form->addItem($nr_field);
775
776 if (!$min_date || $id[1] < $min_date) {
777 $min_date = $id[1];
778 }
779 }
780
781 // recurrence
782 $this->lng->loadLanguageModule("dateplaner");
783 $rec_mode = new ilSelectInputGUI($this->lng->txt("cal_recurrences"), "recm");
784 $rec_mode->setRequired(true);
785 $rec_mode->setOptions(array(
786 "-1" => $this->lng->txt("cal_no_recurrence"),
787 1 => $this->lng->txt("cal_weekly"),
788 2 => $this->lng->txt("r_14"),
789 4 => $this->lng->txt("r_4_weeks")
790 ));
791 $form->addItem($rec_mode);
792
793 $rec_end = new ilDateTimeInputGUI($this->lng->txt("cal_repeat_until"), "rece");
794 $rec_end->setRequired(true);
795 $rec_mode->addSubItem($rec_end);
796
797 if (!$a_reload) {
798 // show date only if active recurrence
799 $rec_mode->setHideSubForm(true, '>= 1');
800
801 if ($min_date) {
802 $rec_end->setDate(new ilDateTime($min_date, IL_CAL_UNIX));
803 }
804 } else {
805 // recurrence may not be changed on reload
806 $rec_mode->setDisabled(true);
807 $rec_end->setDisabled(true);
808 }
809
810 if ($a_group_id) {
811 $grp = new ilHiddenInputGUI("grp_id");
812 $grp->setValue($a_group_id);
813 $form->addItem($grp);
814 }
815
816 if ($this->user_id_assigner !== $this->user_id_to_book) {
817 $usr = new ilHiddenInputGUI("bkusr");
818 $usr->setValue($this->user_id_to_book);
819 $form->addItem($usr);
820 }
821
822 $form->addCommandButton("confirmedBookingNumbers", $this->lng->txt("confirm"));
823 $form->addCommandButton("back", $this->lng->txt("cancel"));
824
825 return $form;
826 }
827
828 public function confirmedBookingNumbers(): void
829 {
830
831 //get the user who will get the booking.
832 if ($this->book_request->getBookedUser() > 0) {
833 $this->user_id_to_book = $this->book_request->getBookedUser();
834 }
835
836 // convert post data to initial form config
837 $counter = array();
838 $current_first = $obj_id = null;
839 foreach (array_keys($this->raw_post_data) as $id) {
840 if (str_starts_with($id, "conf_nr__")) {
841 $id = explode("_", substr($id, 9));
842 $counter[$id[0] . "_" . $id[1] . "_" . $id[2]] = (int) $id[3];
843 if (!$current_first) {
844 $current_first = date("Y-m-d", $id[1]);
845 }
846 }
847 }
848
849 // recurrence
850
851 // checkInput() has not been called yet, so we have to improvise
852 $rece = $this->book_request->getRece();
853 $recm = $this->book_request->getRecm();
854 $end = ilCalendarUtil::parseIncomingDate($rece, false);
855
856 $new_values = [];
857
858 if ((int) $recm > 0 && $end && $current_first) {
859 ksort($counter);
860 $end = $end->get(IL_CAL_DATE);
861 $cycle = (int) $recm * 7;
862 $cut = 0;
863 $org = $counter;
864 while ($cut < 1000 && $this->addDaysDate($current_first, $cycle) <= $end) {
865 $cut++;
866 $current_first = null;
867 foreach ($org as $item_id => $max) {
868 $parts = explode("_", $item_id);
869 $obj_id = $parts[0];
870
871 $from = $this->addDaysStamp($parts[1], $cycle * $cut);
872 $to = $this->addDaysStamp($parts[2], $cycle * $cut);
873
874 $new_item_id = $obj_id . "_" . $from . "_" . $to;
875
876 // form reload because of validation errors
877 if (!isset($counter[$new_item_id]) && date("Y-m-d", $to) <= $end) {
878 // get max available for added dates
879 $new_max = ilBookingReservation::getAvailableObject(array($obj_id), $from, $to - 1, false, true);
880 $new_max = (int) $new_max[$obj_id];
881
882 $counter[$new_item_id] = $new_max;
883
884 if (!$current_first) {
885 $current_first = date("Y-m-d", $from);
886 }
887
888 // clone input
889 $new_values["conf_nr__" . $new_item_id . "_" . $new_max] =
890 $_POST["conf_nr__" . $item_id . "_" . $max];
891 }
892 }
893 }
894 }
895
896 $group_id = $this->book_request->getGroupId();
897
898 $form = $this->initBookingNumbersForm($counter, $group_id, true, $new_values);
899 if ($form->checkInput()) {
900 $success = false;
901 $rsv_ids = array();
902 foreach ($counter as $id => $all_nr) {
903 $book_nr = $form->getInput("conf_nr__" . $id . "_" . $all_nr);
904 $parts = explode("_", $id);
905 $obj_id = $parts[0];
906 $from = $parts[1];
907 $to = $parts[2] - 1;
908
909 // get currently available slots
910 $counter = ilBookingReservation::getAvailableObject(array($obj_id), $from, $to, false, true);
911 $counter = $counter[$obj_id];
912 if ($counter) {
913 // we can only book what is left
914 $book_nr = min($book_nr, $counter);
915 for ($loop = 0; $loop < $book_nr; $loop++) {
916 $rsv_ids[] = $this->processBooking($obj_id, $from, $to, $group_id);
917 $success = $obj_id;
918 }
919 }
920 }
921 if ($success) {
922 $this->saveParticipant();
923 $this->handleBookingSuccess($success, $rsv_ids);
924 } else {
925 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('book_reservation_failed'), true);
926 $this->back();
927 }
928 } else {
929 // ilDateTimeInputGUI does NOT add hidden values on disabled!
930
931 $rece_array = explode(".", $rece);
932
933 $rece_day = str_pad($rece_array[0], 2, "0", STR_PAD_LEFT);
934 $rece_month = str_pad($rece_array[1], 2, "0", STR_PAD_LEFT);
935 $rece_year = $rece_array[2];
936
937 // ilDateTimeInputGUI will choke on POST array format
938 //$_POST["rece"] = null;
939
940 $form->setValuesByPost();
941
942 $rece_date = new ilDate($rece_year . "-" . $rece_month . "-" . $rece_day, IL_CAL_DATE);
943
944 $rece = $form->getItemByPostVar("rece");
945 if ($rece !== null) {
946 $rece->setDate($rece_date);
947 }
948 $recm = $form->getItemByPostVar("recm");
949 if ($recm !== null) {
950 $recm->setHideSubForm((int) $form->getInput("recm") < 1);
951 }
952
953 $hidden_date = new ilHiddenInputGUI("rece");
954 $hidden_date->setValue($rece_date);
955 $form->addItem($hidden_date);
956
957 $this->confirmBookingNumbers($counter, $group_id, $form);
958 }
959 }
960
961 protected function addDaysDate(
962 string $a_date,
963 int $a_days
964 ): string {
965 $date = date_parse($a_date);
966 $stamp = mktime(0, 0, 1, $date["month"], $date["day"] + $a_days, $date["year"]);
967 return date("Y-m-d", $stamp);
968 }
969
970 protected function addDaysStamp(
971 int $a_stamp,
972 int $a_days
973 ): int {
974 $date = getdate($a_stamp);
975 return mktime(
976 $date["hours"],
977 $date["minutes"],
978 $date["seconds"],
979 $date["mon"],
980 $date["mday"] + $a_days,
981 $date["year"]
982 );
983 }
984
985 //
986 // Step 3: Display post success info
987 //
988
989 protected function handleBookingSuccess(
990 int $a_obj_id,
991 array $a_rsv_ids = null
992 ): void {
993 $this->tpl->setOnScreenMessage('success', $this->lng->txt('book_reservation_confirmed'), true);
994
995 // show post booking information?
996 $obj = new ilBookingObject($a_obj_id);
997 $pfile = $obj->getPostFile();
998 $ptext = $obj->getPostText();
999
1000 if (trim($ptext) || $pfile) {
1001 if (count($a_rsv_ids)) {
1002 $this->ctrl->setParameter($this, 'rsv_ids', implode(";", $a_rsv_ids));
1003 }
1004 $this->ctrl->redirect($this, 'displayPostInfo');
1005 } else {
1006 $this->back();
1007 }
1008 }
1009
1013 public function displayPostInfo(): void
1014 {
1015 $tpl = $this->tpl;
1016 $lng = $this->lng;
1017 $ilCtrl = $this->ctrl;
1018 $id = $this->book_obj_id;
1019 if (!$id) {
1020 return;
1021 }
1022 // placeholder
1023 $book_ids = ilBookingReservation::getObjectReservationForUser($id, $this->user_id_assigner);
1024 $tmp = array();
1025 foreach ($book_ids as $book_id) {
1026 if (in_array($book_id, $this->rsv_ids) || count($this->rsv_ids) === 0) {
1027 $obj = new ilBookingReservation($book_id);
1028 $from = $obj->getFrom();
1029 $to = $obj->getTo();
1030 if ($from > time()) {
1031 $key = $from . "-" . $to;
1032 if (!isset($tmp[$key])) {
1033 $tmp[$key] = 0;
1034 }
1035 $tmp[$key]++;
1036 }
1037 }
1038 }
1039
1042
1043 $period = array();
1044 ksort($tmp);
1045 foreach ($tmp as $time => $counter) {
1046 $time = explode("-", $time);
1048 new ilDateTime($time[0], IL_CAL_UNIX),
1049 new ilDateTime($time[1], IL_CAL_UNIX)
1050 );
1051 if ($counter > 1) {
1052 $time .= " (" . $counter . ")";
1053 }
1054 $period[] = $time;
1055 }
1056 $book_id = array_shift($book_ids);
1057
1059
1060
1061 /*
1062 #23578 since Booking pool participants.
1063 $obj = new ilBookingReservation($book_id);
1064 if ($obj->getUserId() != $ilUser->getId())
1065 {
1066 return;
1067 }
1068 */
1069
1070 $obj = new ilBookingObject($id);
1071 $pfile = $obj->getPostFile();
1072 $ptext = $obj->getPostText();
1073
1074 $mytpl = new ilTemplate('tpl.booking_reservation_post.html', true, true, 'Modules/BookingManager/BookingProcess');
1075 $mytpl->setVariable("TITLE", $lng->txt('book_post_booking_information'));
1076
1077 if ($ptext) {
1078 // placeholder
1079 $ptext = str_replace(
1080 ["[OBJECT]", "[PERIOD]"],
1081 [$obj->getTitle(), implode("<br />", $period)],
1082 $ptext
1083 );
1084
1085 $mytpl->setVariable("POST_TEXT", nl2br($ptext));
1086 }
1087
1088 if ($pfile) {
1089 $url = $ilCtrl->getLinkTarget($this, 'deliverPostFile');
1090
1091 $mytpl->setVariable("DOWNLOAD", $lng->txt('download'));
1092 $mytpl->setVariable("URL_FILE", $url);
1093 $mytpl->setVariable("TXT_FILE", $pfile);
1094 }
1095
1096 $mytpl->setVariable("TXT_SUBMIT", $lng->txt('ok'));
1097 $mytpl->setVariable("URL_SUBMIT", $ilCtrl->getLinkTarget($this, "back"));
1098
1099 $tpl->setContent($mytpl->get());
1100 }
1101
1105 public function deliverPostFile(): void
1106 {
1107 $id = $this->book_obj_id;
1108 if (!$id) {
1109 return;
1110 }
1111
1112 $book_ids = ilBookingReservation::getObjectReservationForUser($id, $this->user_id_assigner);
1113 $book_id = current($book_ids);
1114 $obj = new ilBookingReservation($book_id);
1115 if ($obj->getUserId() !== $this->user_id_assigner) {
1116 return;
1117 }
1118
1119 $obj = new ilBookingObject($id);
1120 $file = $obj->getPostFileFullPath();
1121 if ($file) {
1122 ilFileDelivery::deliverFileLegacy($file, $obj->getPostFile());
1123 }
1124 }
1125}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
const IL_CAL_UNIX
return true
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getNrOfItemsForObjects(array $a_obj_ids)
Get nr of available items for a set of object ids.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilBookingHelpAdapter $help
confirmBookingNumbers(array $a_objects_counter, int $a_group_id, ilPropertyFormGUI $a_form=null)
addDaysDate(string $a_date, int $a_days)
saveMultipleBookings()
Save multiple users reservations for one booking pool object.
bookMultipleParticipants()
Create reservations for a bunch of booking pool participants.
displayPostInfo()
Display post booking informations.
ilGlobalTemplateInterface $tpl
addDaysStamp(int $a_stamp, int $a_days)
book()
First step in booking process.
handleBookingSuccess(int $a_obj_id, array $a_rsv_ids=null)
initBookingNumbersForm(array $a_objects_counter, int $a_group_id, bool $a_reload=false, ?array $new_values=null)
processBooking(int $a_object_id, int $a_from=null, int $a_to=null, int $a_group_id=null)
Book object for date.
saveParticipant()
save booking participant
deliverPostFile()
Deliver post booking file.
ILIAS BookingManager StandardGUIRequest $book_request
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getObjectReservationForUser(int $a_object_id, int $a_user_id)
static isObjectAvailableNoSchedule(int $a_obj_id)
static numAvailableFromObjectNoSchedule(int $a_obj_id)
static getAvailableObject(array $a_ids, int $a_from, int $a_to, bool $a_return_single=true, bool $a_return_counter=false)
Check if any of given objects are bookable.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getColorsByType(string $a_type)
get selectable colors
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getInstanceByUserId(int $a_user_id)
static calculateFontColor(string $a_html_color_code)
Calculate best font color from html hex color code.
static _buildWeekDayList(ilDate $a_day, int $a_weekstart)
build week day list @access public
static parseIncomingDate($a_value, bool $a_add_time=false)
Try to parse incoming value to date object.
static _numericDayToString(int $a_day, bool $a_long=true)
static _numericMonthToString(int $a_month, bool $a_long=true)
numeric month to string
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...
Class ilCtrl provides processing control methods.
getNextClass($a_gui_class=null)
@inheritDoc
getCmd(string $fallback_command=null)
@inheritDoc
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false)
Format a period of two dates Shows: 14.
static setUseRelativeDates(bool $a_status)
set use relative dates
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
@classDescription Date and time handling
Class for single dates.
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
setFormAction(string $a_formaction)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
language handling
This class represents a number property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
User class.
static _lookupFullname(int $a_user_id)
This class represents a property form user interface.
This class represents a selection list property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setContent(string $a_html)
Sets content for standard template.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
if($format !==null) $name
Definition: metadata.php:247
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
$url
$lng