19declare(strict_types=1);
57 private readonly UIFactory $ui_factory,
69 private readonly
int $booking_context_obj_id,
70 private readonly array $bookable_items,
86 $schedule_type = $this->pool->getScheduleType();
96 return $this->
access->canManageOwnReservations($this->ref_id) || $this->
access->canManageObjects($this->ref_id);
101 $schedule_type = $this->pool->getScheduleType();
106 return $record[
'is_available'] ??
false;
118 ->withParameter($action_token, $this->
getActionId())
119 ->withParameter($action_type_token, self::SHOW_MODAL_ACTION),
130 $selected_records = $this->
http->resolveRowParameters($row_id_token->getName());
132 if ($all_records_selected) {
133 $selected_records = array_keys($this->bookable_items);
136 $selected_records = $this->resolveBookingEntriesPayload($this->
lng, $selected_records);
137 $selected_records[
'entries'] = array_values(array_filter(
138 $selected_records[
'entries'],
139 fn(array $entry):
bool => $this->allowActionForRecord($entry)
143 $remaining = $this->getRemainingBookingCapacity();
144 if ($remaining !==
null && count($selected_records[
'entries']) > $remaining) {
145 $this->
http->sendAsync(
146 $this->ui_renderer->renderAsync(
147 $this->buildBookModalInformative(
148 $this->lng->txt(
'book_overall_limit_would_be_exceeded')
156 $this->
http->sendAsync(
157 $this->ui_renderer->renderAsync(
162 $all_records_selected
164 : array_column($selected_records[
'entries'],
'row_id')
166 ->withParameter($action_token, $this->getActionId())
169 $all_records_selected
177 array $selected_records,
178 bool $all_records_selected
180 $entries = $selected_records[
'entries'];
181 if ($entries === []) {
182 return $this->buildBookModalInformative($this->
lng->txt(
'no_valid_selection'));
186 foreach ($entries as $entry) {
187 $grouped[$entry[
'booking_object_id']][] = $entry;
191 $skipped_descriptions = $selected_records[
'skipped_descriptions'];
193 if ($skipped_descriptions !== []) {
195 $this->ui_factory->messageBox()->confirmation(
196 $this->
lng->txt(
'book_modal_warning_skipped_selections')
197 . $this->ui_renderer->render($this->ui_factory->listing()->unordered($skipped_descriptions))
202 $form_components = [];
203 $field_factory = $this->ui_factory->input()->field();
204 foreach ($grouped as $object_id => $entries) {
205 $section_input_components = [];
207 foreach ($entries as $entry) {
208 if (!$entry[
'has_schedule']) {
212 $max_quantity = $entry[
'max_quantity'];
214 $section_input_components[$entry[
'row_id']] = $field_factory->numeric(
215 $this->formatBookModalSlotLabel($entry[
'slot_from'], $entry[
'slot_to']),
216 sprintf($this->
lng->txt(
'book_objects_available'), $max_quantity)
219 ->withAdditionalTransformation(
220 $this->
refinery->logical()->parallel(
222 $this->refinery->int()->isGreaterThanOrEqual(1),
223 $this->refinery->int()->isLessThanOrEqual($max_quantity)
227 ->withAdditionalOnLoadCode(
228 static fn(
string $id):
string
230 var element = document.getElementById('{$id}').querySelector('div input');
232 element.max = {$max_quantity};
237 if ($this->pool->usesMessages()) {
238 $section_input_components[
'message'] = $field_factory->textarea(
239 $this->
lng->txt(
'book_message'),
240 $this->lng->txt(
'book_message_info')
244 $form_components[$object_id] = $field_factory->section(
245 $section_input_components,
246 $entries[0][
'title'],
247 $this->
lng->txt(
'book_modal_enter_quantity_intro')
251 return $this->ui_factory->modal()->roundtrip(
252 $this->
lng->txt(
'book_modal_booking_confirmation'),
255 $url_builder->
buildURI()->__toString()
260 URLBuilder $url_builder,
261 array $selected_records,
262 bool $all_records_selected
265 $remaining = $this->getRemainingBookingCapacity();
266 if ($remaining !==
null && count($selected_records) > $remaining) {
267 return $this->buildBookModalInformative(
268 $this->
lng->txt(
'book_overall_limit_warning')
278 'entries' => $selected_records,
279 'skipped_descriptions' => []
281 $all_records_selected
283 $modal = $modal->withRequest($this->
http->getRequest());
286 $data = $modal->getData();
287 if (
$data ===
null) {
288 return $modal->withOnLoad($modal->getShowSignal());
294 foreach (
$data as $object_id => $section) {
295 $message = $section[
'message'] ??
'';
296 unset($section[
'message']);
299 if ($section === [] && !$bookable_item->getScheduleId()) {
300 $section = [$object_id => 1];
303 foreach ($section as $row_id => $amount) {
304 $from_to = $bookable_item->getScheduleId() ? explode(
'_', $row_id) : [];
306 $booked = $this->process_manager->bookAvailableObjects(
307 $bookable_item->getId(),
308 $this->user->getId(),
309 $this->user->getId(),
310 $this->booking_context_obj_id,
311 (
int) ($from_to[1] ?? 0),
312 (
int) ($from_to[2] ?? 0),
319 if ($booked !== []) {
320 $booked_total += count($booked);
324 $unavailable[] = $row_id;
328 if ($unavailable !== []) {
329 $this->tpl->setOnScreenMessage(
331 $this->
lng->txt(
'book_some_reservations_unavailable'),
336 if ($booked_total === 0 && $unavailable === []) {
337 $this->tpl->setOnScreenMessage(
339 $this->
lng->txt(
'book_reservation_failed'),
344 if ($booked_total > 0) {
345 $this->tpl->setOnScreenMessage(
347 $this->
lng->txt(
'book_reservation_confirmed'),
352 $this->
ctrl->redirectByClass(ilBookingObjectGUI::class,
'render');
362 return $this->resolveBookingEntriesPayload(
364 $selected_ids ?? array_keys($this->bookable_items)
370 return $this->ui_factory->modal()->roundtrip(
371 $this->
lng->txt(
'book_modal_booking_confirmation'),
372 [$this->ui_factory->messageBox()->failure($message)]
378 if (!is_array($row_ids)) {
379 $row_ids = $row_ids === HttpService::ALL_OBJECTS ? array_keys($this->bookable_items) : [];
383 $skipped_descriptions = [];
385 foreach ($row_ids as $row_id) {
386 $row_key = (string) $row_id;
387 $record = $this->bookable_items[$row_key] ??
null;
388 if ($record ===
null) {
389 $skipped_descriptions[] = sprintf(
$lng->txt(
'book_modal_skipped_unknown_item'), $row_key);
393 $availability = (
int) ($record[
'available'] ?? 0);
394 $has_schedule = ($record[
'schedule_id'] ?? 0) > 0;
395 $slot_from = (
int) ($record[
'slot_from'] ?? 0);
396 $slot_to = (
int) ($record[
'slot_to'] ?? 0);
398 if ($availability <= 0) {
399 $skipped_descriptions[] = $has_schedule
403 $this->formatBookModalSlotLabel($slot_from, $slot_to)
409 if (!$has_schedule && ($record[
'has_user_active_booking'] ??
false)) {
410 $skipped_descriptions[] = $record[
'title'];
415 'row_id' => $row_key,
416 'booking_object_id' => (
int) $record[
'booking_object_id'],
417 'title' => (
string) $record[
'title'],
418 'has_schedule' => $has_schedule,
419 'has_user_booking' => (bool) ($record[
'has_user_booking'] ??
false),
420 'slot_from' => $slot_from,
421 'slot_to' => $slot_to,
422 'max_quantity' => $availability,
423 'is_available' =>
true,
428 'entries' => $entries,
429 'skipped_descriptions' => $skipped_descriptions,
435 $this->
lng->loadLanguageModule(
'dateplaner');
445 $limit = $this->pool->getOverallLimit();
446 if ($limit ===
null || $limit === 0) {
451 $this->
user->getId(),
455 return max(0, $limit - $current);
460 return $this->getRemainingBookingCapacity() === 0;
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
isUserBookingPoolLimitReached()
__construct(private readonly UIFactory $ui_factory, private readonly UIRenderer $ui_renderer, private readonly ilGlobalTemplateInterface $tpl, private readonly ilLanguage $lng, private readonly HttpService $http, private readonly Refinery $refinery, private readonly ilCtrlInterface $ctrl, private readonly AccessManager $access, private readonly ilObjBookingPool $pool, private readonly BookingProcessManager $process_manager, private readonly ilObjUser $user, private readonly int $ref_id, private readonly int $booking_context_obj_id, private readonly array $bookable_items,)
const string ACTION_LABEL
allowActionForRecord(mixed $record)
getModal(URLBuilder $url_builder, array $selected_records, bool $all_records_selected)
formatBookModalSlotLabel(int $slot_from, int $slot_to)
resolveBookingEntriesPayload(ilLanguage $lng, string|array $row_ids)
buildBookModalInformative(string $message)
resolveRecords(?array $selected_ids=null)
showModal(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token)
getRemainingBookingCapacity()
getTableAction(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token)
Builds a Color from either hex- or rgb values.
buildURI()
Get a URI representation of the full URL including query string and fragment/hash.
withParameter(URLBuilderToken $token, string|array $value)
Change an acquired parameter's value if the supplied token is valid.
@ilCtrl_Calls ilBookingObjectGUI: ilPropertyFormGUI, ilBookingProcessWithScheduleGUI,...
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 isBookingPoolLimitReachedByUser(int $a_user_id, int $a_pool_id)
Class for date presentation.
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false, ?ilObjUser $user=null)
Format a period of two dates Shows: 14.
@classDescription Date and time handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const TYPE_NO_SCHEDULE_PREFERENCES
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const MESSAGE_TYPE_SUCCESS
const MESSAGE_TYPE_FAILURE
withAdditionalOnLoadCode(Closure $binder)
Add some onload-code to the component instead of replacing the existing one.
This describes commonalities between the different modals.
An entity that renders components to a string output.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
readonly HttpService $http
readonly UIRenderer $ui_renderer
trait TableActionModalTrait
@template RecordType
const string SUBMIT_MODAL_ACTION
onSubmit(URLBuilder $url_builder, array $selected_records, bool $all_records_selected)
static http()
Fetches the global http state from ILIAS.
if(!file_exists('../ilias.ini.php'))