diff --git a/components/ILIAS/BookingManager/BookingProcess/class.ProcessUtilGUI.php b/components/ILIAS/BookingManager/BookingProcess/class.ProcessUtilGUI.php index 1ddab4e7782f..3f24055f45a6 100755 --- a/components/ILIAS/BookingManager/BookingProcess/class.ProcessUtilGUI.php +++ b/components/ILIAS/BookingManager/BookingProcess/class.ProcessUtilGUI.php @@ -76,6 +76,11 @@ public function back(): void return; } + if ($retCmd === 'render') { + $this->redirectToRender(); + return; + } + if ($retCmd !== "") { $this->ctrl->redirectByClass(get_class($this->parent_gui), $retCmd); } else { @@ -184,107 +189,205 @@ public function displayPostInfo( int $user_id, string $file_deliver_cmd ): void { - $this->log->debug("displayPostInfo"); - $main_tpl = $this->gui->mainTemplate(); - $ctrl = $this->gui->ctrl(); - $lng = $this->domain->lng(); - $id = $book_obj_id; - $request = $this->gui->standardRequest(); + $this->log->debug('displayPostInfo'); + $booking_ids = $this->request->getReservationIdsFromString(); - if (!$id) { + $objects_with_periods = $this->resolveObjectsWithPeriodsForPostInfo( + $book_obj_id, + $user_id, + $booking_ids + ); + + if ($objects_with_periods === []) { + $this->ctrl->redirect($this->parent_gui, 'back'); return; } - $rsv_ids = $request->getReservationIdsFromString(); - - $tmp = []; - if ($rsv_ids === [] && $request->getReservationId() !== '') { - $reservationIdParts = explode('_', $request->getReservationId()); + $booking_objects = []; + $booking_info_filenames = []; - $user_id = (int) ($reservationIdParts[1] ?? 0); - $from = (int) ($reservationIdParts[2] ?? 0); + $objects_with_info = []; + foreach ($objects_with_periods as $object_id => $periods) { + $booking_objects[$object_id] = new \ilBookingObject($object_id); + $booking_info_filenames[$object_id] = trim($this->objects_manager->getBookingInfoFilename($object_id)); - if ($from > time()) { - $to = (int) ($reservationIdParts[3] ?? 0); - $tmp["$from-" . ($to + 1)] = 1; + if ( + trim($booking_objects[$object_id]->getPostText()) === '' + && $booking_info_filenames[$object_id] === '' + ) { + continue; } - $rsv_ids = [0]; + + $objects_with_info[$object_id] = $periods; } - // placeholder + if ($objects_with_info === []) { + $this->ctrl->redirect($this->parent_gui, 'back'); + return; + } - $book_ids = \ilBookingReservation::getObjectReservationForUser($id, $user_id); - foreach ($book_ids as $book_id) { - if (in_array($book_id, $rsv_ids) || count($rsv_ids) === 0) { - $obj = new \ilBookingReservation($book_id); - $from = $obj->getFrom(); - $to = $obj->getTo(); - if ($from > time()) { - $tmp[$from . "-" . $to + 1] = $tmp[$from . "-" . $to + 1] ?? 0; - $tmp[$from . "-" . $to + 1]++; - } + $template = new \ilTemplate( + 'tpl.booking_reservation_post.html', + true, + true, + 'components/ILIAS/BookingManager/BookingProcess' + ); + $multiple_objects = count($objects_with_info) > 1; + $submit_url = $this->ctrl->getLinkTarget($this->parent_gui, 'back'); + + foreach ($objects_with_info as $object_id => $periods) { + $booking_object = $booking_objects[$object_id]; + $post_text = trim($booking_object->getPostText()); + + $template->setCurrentBlock('info_block'); + $title = $multiple_objects + ? sprintf($this->lng->txt('book_post_booking_information_for'), $booking_object->getTitle()) + : $this->lng->txt('book_post_booking_information'); + $template->setVariable('TITLE', $title); + + if ($post_text !== '') { + $post_text = str_replace( + ['[OBJECT]', '[PERIOD]'], + [$booking_object->getTitle(), implode('
', $periods)], + $post_text + ); + $template->setVariable('POST_TEXT', nl2br($post_text)); + } + + if ($booking_info_filenames[$object_id] === '') { + $template->parseCurrentBlock(); + continue; } + + $this->ctrl->setParameter($this->parent_gui, 'object_id', $object_id); + $url = $this->ctrl->getLinkTarget($this->parent_gui, $file_deliver_cmd); + $this->ctrl->clearParameterByClass($this->parent_gui::class, 'object_id'); + + $template->setCurrentBlock('download'); + $template->setVariable('DOWNLOAD', $this->lng->txt('download')); + $template->setVariable('URL_FILE', $url); + $template->setVariable('TXT_FILE', $booking_info_filenames[$object_id]); + $template->parseCurrentBlock(); + $template->setCurrentBlock('info_block'); + + $template->parseCurrentBlock(); } - $olddt = \ilDatePresentation::useRelativeDates(); - \ilDatePresentation::setUseRelativeDates(false); + $template->setCurrentBlock('submit'); + $template->setVariable('TXT_SUBMIT', $this->lng->txt('ok')); + $template->setVariable('URL_SUBMIT', $submit_url); + $template->parseCurrentBlock(); - $period = array(); - ksort($tmp); - foreach ($tmp as $time => $counter) { - $time = explode("-", $time); - $time = \ilDatePresentation::formatPeriod( - new \ilDateTime($time[0], IL_CAL_UNIX), - new \ilDateTime($time[1], IL_CAL_UNIX) - ); - if ($counter > 1) { - $time .= " (" . $counter . ")"; + $this->tpl->setContent($template->get()); + } + + /** + * @return array + */ + protected function resolveObjectsWithPeriodsForPostInfo( + int $book_obj_id, + int $user_id, + array $booking_ids + ): array { + if ($booking_ids !== []) { + return $this->resolvePeriodsFromReservationIds($booking_ids); + } + + if ($book_obj_id <= 0) { + return []; + } + + $period_slots = []; + if ($this->request->getReservationId() !== '') { + $reservation_id_parts = explode('_', $this->request->getReservationId()); + $user_id = (int) ($reservation_id_parts[1] ?? 0); + $from = (int) ($reservation_id_parts[2] ?? 0); + + if ($from > time()) { + $to = (int) ($reservation_id_parts[3] ?? 0); + $period_slots["$from-$to"] = 1; } - $period[] = $time; + $booking_ids = [0]; } - $book_id = array_shift($book_ids); - \ilDatePresentation::setUseRelativeDates($olddt); + $book_ids = \ilBookingReservation::getObjectReservationForUser($book_obj_id, $user_id); + foreach ($book_ids as $book_id) { + if (!in_array($book_id, $booking_ids, true) && $booking_ids !== []) { + continue; + } - /* - #23578 since Booking pool participants. - $obj = new ilBookingReservation($book_id); - if ($obj->getUserId() != $ilUser->getId()) - { - return; + $reservation = new \ilBookingReservation($book_id); + $from = $reservation->getFrom(); + $to = $reservation->getTo(); + if ($from > time()) { + $key = "$from-$to"; + $period_slots[$key] = ($period_slots[$key] ?? 0) + 1; + } } - */ - $obj = new \ilBookingObject($id); - $pfile = $this->objects_manager->getBookingInfoFilename($id); - $ptext = $obj->getPostText(); + return $period_slots === [] + ? [] + : [$book_obj_id => $this->formatPeriodSlots($period_slots)]; + } - $mytpl = new \ilTemplate('tpl.booking_reservation_post.html', true, true, 'components/ILIAS/BookingManager/BookingProcess'); - $mytpl->setVariable("TITLE", $lng->txt('book_post_booking_information')); + /** + * @param string[] $booking_ids + * @return array + */ + protected function resolvePeriodsFromReservationIds(array $booking_ids): array + { + $period_slots_by_object = []; - if ($ptext) { - // placeholder - $ptext = str_replace( - ["[OBJECT]", "[PERIOD]"], - [$obj->getTitle(), implode("
", $period)], - $ptext - ); + foreach ($booking_ids as $booking_id) { + $booking_id = (int) $booking_id; + if ($booking_id <= 0) { + continue; + } - $mytpl->setVariable("POST_TEXT", nl2br($ptext)); + $reservation = new \ilBookingReservation($booking_id); + $object_id = $reservation->getObjectId(); + $key = "{$reservation->getFrom()}-{$reservation->getTo()}"; + $period_slots_by_object[$object_id][$key] = ($period_slots_by_object[$object_id][$key] ?? 0) + 1; } - if ($pfile) { - $url = $ctrl->getLinkTarget($this->parent_gui, $file_deliver_cmd); + $objects_with_periods = []; + foreach ($period_slots_by_object as $object_id => $period_slots) { + $objects_with_periods[$object_id] = $this->formatPeriodSlots($period_slots); + } + + ksort($objects_with_periods); + + return $objects_with_periods; + } + + /** + * @param array $period_slots + * @return string[] + */ + protected function formatPeriodSlots(array $period_slots): array + { + $olddt = \ilDatePresentation::useRelativeDates(); + \ilDatePresentation::setUseRelativeDates(false); + + $period = []; + ksort($period_slots); + foreach ($period_slots as $time => $counter) { + $time_parts = explode('-', $time); + $formatted = \ilDatePresentation::formatPeriod( + new \ilDateTime((int) $time_parts[0], IL_CAL_UNIX), + new \ilDateTime((int) $time_parts[1], IL_CAL_UNIX) + ); - $mytpl->setVariable("DOWNLOAD", $lng->txt('download')); - $mytpl->setVariable("URL_FILE", $url); - $mytpl->setVariable("TXT_FILE", $pfile); + if ($counter > 1) { + $formatted .= " ($counter)"; + } + + $period[] = $formatted; } - $mytpl->setVariable("TXT_SUBMIT", $lng->txt('ok')); - $mytpl->setVariable("URL_SUBMIT", $ctrl->getLinkTarget($this->parent_gui, "back")); + \ilDatePresentation::setUseRelativeDates($olddt); - $main_tpl->setContent($mytpl->get()); + return $period; } /** diff --git a/components/ILIAS/BookingManager/BookingProcess/templates/default/tpl.booking_reservation_post.html b/components/ILIAS/BookingManager/BookingProcess/templates/default/tpl.booking_reservation_post.html index 53621b1bdba5..c54fee6730f1 100755 --- a/components/ILIAS/BookingManager/BookingProcess/templates/default/tpl.booking_reservation_post.html +++ b/components/ILIAS/BookingManager/BookingProcess/templates/default/tpl.booking_reservation_post.html @@ -1,3 +1,4 @@ +

{TITLE}

@@ -13,9 +14,10 @@

{TITLE}

- - \ No newline at end of file + + + + + diff --git a/components/ILIAS/BookingManager/src/BookableItem/Table/Action/BookableItemTableBookAction.php b/components/ILIAS/BookingManager/src/BookableItem/Table/Action/BookableItemTableBookAction.php index c0ae73b87720..ca6a4468b19d 100644 --- a/components/ILIAS/BookingManager/src/BookableItem/Table/Action/BookableItemTableBookAction.php +++ b/components/ILIAS/BookingManager/src/BookableItem/Table/Action/BookableItemTableBookAction.php @@ -21,6 +21,8 @@ namespace ILIAS\BookingManager\BookableItem\Table\Action; use ilBookingObjectGUI; +use ilBookingProcessWithScheduleGUI; +use ilBookingProcessWithoutScheduleGUI; use ilBookingReservation; use ilCtrlInterface; use ilDatePresentation; @@ -43,8 +45,6 @@ use ilBookingObject; use ILIAS\BookingManager\BookingProcess\BookingProcessManager; use ilObjUser; -use DateTimeZone; -use DateTime; class BookableItemTableBookAction implements TableAction { @@ -290,6 +290,7 @@ public function onSubmit( $booked_total = 0; $unavailable = []; + $booking_ids = []; foreach ($data as $object_id => $section) { $message = $section['message'] ?? ''; @@ -318,6 +319,9 @@ public function onSubmit( if ($booked !== []) { $booked_total += count($booked); + foreach ($booked as $booking_id) { + $booking_ids[] = $booking_id; + } continue; } @@ -347,6 +351,15 @@ public function onSubmit( $this->lng->txt('book_reservation_confirmed'), true ); + + $booking_process_gui_class = $this->pool->getScheduleType() === ilObjBookingPool::TYPE_FIX_SCHEDULE + ? ilBookingProcessWithScheduleGUI::class + : ilBookingProcessWithoutScheduleGUI::class; + + $this->ctrl->setParameterByClass($booking_process_gui_class, 'rsv_ids', implode(';', array_unique($booking_ids))); + $this->ctrl->setParameterByClass($booking_process_gui_class, 'returnCmd', 'render'); + $this->ctrl->redirectByClass($booking_process_gui_class, 'displayPostInfo'); + return null; } $this->ctrl->redirectByClass(ilBookingObjectGUI::class, 'render'); diff --git a/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingTableActionsFactory.php b/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingTableActionsFactory.php index 44502a36de95..c3ba8b9cf3f6 100644 --- a/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingTableActionsFactory.php +++ b/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingTableActionsFactory.php @@ -23,6 +23,7 @@ use ilCtrlInterface; use ilGlobalTemplateInterface; use ILIAS\BookingManager\Access\AccessManager; +use ILIAS\BookingManager\Bookings\Table\Action\BookingsTableBookingInformationAction; use ILIAS\BookingManager\Bookings\Table\Action\BookingsTableCancelAction; use ILIAS\BookingManager\Bookings\Table\Action\BookingsTableDeleteAction; use ILIAS\BookingManager\Bookings\Table\Action\BookingsTableMailAction; @@ -44,6 +45,8 @@ class BookingTableActionsFactory implements TableActionsFactory public const string ACTION_MAIL = 'mail'; + public const string ACTION_BOOKING_INFORMATION = 'booking_information'; + public function __construct( protected readonly ilCtrlInterface $ctrl, protected readonly ilLanguage $lng, @@ -73,6 +76,7 @@ public function getTableActions(): TableActions self::ACTION_CANCEL => $this->getCancelAction(), self::ACTION_DELETE => $this->getDeleteAction(), self::ACTION_MAIL => $this->getMailAction(), + self::ACTION_BOOKING_INFORMATION => $this->getBookingInformationAction(), ] ); } @@ -124,4 +128,16 @@ protected function getMailAction(): BookingsTableMailAction $this->bookings ); } + + protected function getBookingInformationAction(): BookingsTableBookingInformationAction + { + return new BookingsTableBookingInformationAction( + $this->ui_factory, + $this->lng, + $this->http, + $this->tpl, + $this->ctrl, + $this->bookings + ); + } } diff --git a/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingsTableBookingInformationAction.php b/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingsTableBookingInformationAction.php new file mode 100644 index 000000000000..793cbecddfc0 --- /dev/null +++ b/components/ILIAS/BookingManager/src/Booking/Table/Action/BookingsTableBookingInformationAction.php @@ -0,0 +1,130 @@ +ui_factory->table()->action()->standard( + $this->lng->txt($this->getActionLabel()), + $url_builder + ->withParameter($action_token, $this->getActionId()) + ->withParameter($action_type_token, 'booking_information'), + $row_id_token + ); + } + + public function onExecute( + URLBuilder $url_builder, + URLBuilderToken $row_id_token, + URLBuilderToken $action_token, + URLBuilderToken $action_type_token + ): mixed { + $row_parameters = $this->http->resolveRowParameters($row_id_token->getName()); + if ($row_parameters === HttpService::ALL_OBJECTS) { + $selected_ids = null; + } elseif (is_string($row_parameters)) { + $selected_ids = [$row_parameters]; + } else { + $selected_ids = $row_parameters; + } + + $reservation_ids = $this->resolveRecords($selected_ids); + + if ($reservation_ids === []) { + $this->tpl->setOnScreenMessage( + ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE, + $this->lng->txt('no_valid_selection'), + true + ); + return null; + } + + $this->ctrl->setParameterByClass( + ilBookingReservationsGUI::class, + 'rsv_ids', + implode(';', $reservation_ids) + ); + $this->ctrl->redirectByClass(ilBookingReservationsGUI::class, 'displayPostInfo'); + return null; + } + + /** + * @return int[] + */ + protected function resolveRecords(?array $selected_ids = null): array + { + return array_map( + 'intval', + $selected_ids ?? array_keys($this->bookings) + ); + } +} diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 6dc03d2d7716..57098c560267 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -2656,6 +2656,7 @@ book#:#book_pool_added#:#Ein Buchungspool wurde angelegt. book#:#book_pool_selection#:#Auswahl Buchungspool book#:#book_post_booking_file#:#Datei book#:#book_post_booking_information#:#Informationen zur Buchung +book#:#book_post_booking_information_for#:#Informationen zur Buchung von "%s" book#:#book_post_booking_text#:#Text book#:#book_post_booking_text_info#:#Die Platzhalter können genutzt werden, um Buchungsdetails zum Infotext hinzuzufügen.
Der Platzhalter [OBJECT] wird durch das jeweilige Angebot ersetzt.
Der Platzhalter [PERIOD] wird durch den gewählten Buchungszeitraum ersetzt. book#:#book_pref_book_cron#:#Buchung mit Präferenzen diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index b7a53e9a03ee..8fae3ba0770e 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -2657,6 +2657,7 @@ book#:#book_pool_added#:#Booking pool successfully created. book#:#book_pool_selection#:#Booking Pool Selection book#:#book_post_booking_file#:#File book#:#book_post_booking_information#:#Booking Information +book#:#book_post_booking_information_for#:#Booking Information for "%s" book#:#book_post_booking_text#:#Text book#:#book_post_booking_text_info#:#Use placeholders to include booking-specific information.
[OBJECT] will be replaced by the respective Bookable Item.
[PERIOD] will be replaced by the respective schedule. book#:#book_pref_book_cron#:#Booking with Preferences