ILIAS  trunk Revision v12.0_alpha-1613-gae4c99ebb18
BookableItemTableCancelBookingAction.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
26use ilDateTime;
32use ILIAS\Refinery\Factory as Refinery;
36use ILIAS\UI\Factory as UIFactory;
37use ILIAS\UI\Renderer as UIRenderer;
40use ilLanguage;
42use ilObjUser;
43
45{
47
48 public const string ACTION_ID = 'cancel_booking';
49 public const string ACTION_LABEL = 'book_set_cancel';
50 public const string SHOW_MODAL_ACTION = 'showModalAction';
51 public const string SUBMIT_MODAL_ACTION = 'submitModalAction';
52
53 private readonly array $bookings;
54
55 public function __construct(
56 private readonly UIFactory $ui_factory,
57 private readonly UIRenderer $ui_renderer,
58 private readonly ilLanguage $lng,
59 private readonly ilGlobalTemplateInterface $tpl,
60 private readonly HttpService $http,
61 private readonly Refinery $refinery,
62 private readonly AccessManager $access,
63 private readonly ilObjBookingPool $pool,
64 private readonly ilObjUser $user,
65 private readonly int $ref_id,
66 private readonly bool $active_management,
67 private readonly array $bookable_items,
68 ) {
69 $filter = [];
70 if (
71 !$this->access->canManageAllReservations($this->pool->getRefId())
72 && !$this->access->canReadPublicLog($this->pool->getRefId())
73 ) {
74 $filter['user_id'] = $this->user->getId();
75 }
76 $this->bookings = array_column(
77 ilBookingReservation::getList(array_keys($this->bookable_items), 1000, 0, $filter)['data'],
78 null,
79 'booking_reservation_id'
80 );
81 }
82
83 public function getActionId(): string
84 {
85 return self::ACTION_ID;
86 }
87
88 public function getActionLabel(): string
89 {
90 return self::ACTION_LABEL;
91 }
92
93 public function isAvailable(): bool
94 {
95 if ($this->pool->getScheduleType() === ilObjBookingPool::TYPE_NO_SCHEDULE_PREFERENCES) {
96 return false;
97 }
98
99 return
100 $this->active_management
101 && ($this->access->canManageOwnReservations($this->ref_id) || $this->access->canManageObjects($this->ref_id));
102 }
103
104 public function getTableAction(
105 URLBuilder $url_builder,
106 URLBuilderToken $row_id_token,
107 URLBuilderToken $action_token,
108 URLBuilderToken $action_type_token
109 ): Action {
110 return $this->ui_factory->table()->action()->standard(
111 $this->lng->txt(self::ACTION_LABEL),
112 $url_builder
113 ->withParameter($action_token, self::ACTION_ID)
114 ->withParameter($action_type_token, self::SHOW_MODAL_ACTION),
115 $row_id_token
116 )->withAsync();
117 }
118
119 public function allowActionForRecord(mixed $record): bool
120 {
121 return $record['has_user_active_booking'] ?? false;
122 }
123
124 public function onExecute(
125 URLBuilder $url_builder,
126 URLBuilderToken $row_id_token,
127 URLBuilderToken $action_token,
128 URLBuilderToken $action_type_token
129 ): ?Modal {
130 return match ($this->http->resolveRowParameter($action_type_token->getName())) {
131 self::SUBMIT_MODAL_ACTION => $this->submit($url_builder, $row_id_token, $action_token, $action_type_token),
132 default => $this->showModal(
133 $url_builder,
134 $row_id_token,
135 $action_token,
136 $action_type_token
137 ),
138 };
139 }
140
141 protected function getModal(
142 URLBuilder $url_builder,
143 array $selected_records,
144 bool $all_records_selected
145 ): ?Modal {
146 return $this->ui_factory->modal()->interruptive(
147 $this->lng->txt('book_confirm_cancel'),
148 $this->lng->txt('book_confirm_cancel_info'),
149 $url_builder->buildURI()->__toString()
150 )->withAffectedItems(array_map(
151 fn(array $record): InterruptiveItem => $this->ui_factory->modal()->interruptiveItem()->standard(
152 (string) $record['reservation_id'],
153 $this->buildItemDescription($record)
154 ),
155 $this->resolveRecords($selected_records)
156 ))->withActionButtonLabel($this->lng->txt('book_set_cancel'));
157 }
158
159 protected function showModal(
160 URLBuilder $url_builder,
161 URLBuilderToken $row_id_token,
162 URLBuilderToken $action_token,
163 URLBuilderToken $action_type_token
164 ): void {
165 $selected_records = $this->http->resolveRowParameters($row_id_token->getName());
166 $all_records_selected = $selected_records === HttpService::ALL_OBJECTS;
167 if ($all_records_selected) {
168 $selected_records = array_map(
169 fn(array $record): string => "{$record['object_id']}_{$record['date_from']}_{$record['date_to']}",
170 $this->bookings
171 );
172 }
173
174 $this->http->sendAsync(
175 $this->ui_renderer->renderAsync(
176 $this->getModal(
177 $url_builder
179 $row_id_token,
180 $all_records_selected
181 ? HttpService::ALL_OBJECTS
182 : $selected_records
183 )
184 ->withParameter($action_token, self::ACTION_ID)
185 ->withParameter($action_type_token, self::SUBMIT_MODAL_ACTION),
186 $selected_records,
187 $all_records_selected
188 )
189 )
190 );
191 }
192
193 protected function onSubmit(
194 URLBuilder $url_builder,
195 array $selected_records,
196 bool $all_records_selected
197 ): ?Modal {
198 if (!$this->access->canManageOwnReservations($this->ref_id)) {
199 $this->tpl->setOnScreenMessage(
201 $this->lng->txt('no_permission'),
202 true
203 );
204 return null;
205 }
206
207 $cancelled = 0;
208 foreach ($selected_records as $record) {
209 $reservation = new ilBookingReservation((int) $record['reservation_id']);
210 $reservation->setStatus(ilBookingReservation::STATUS_CANCELLED);
211 $reservation->update();
212 $cancelled++;
213 }
214
215 if ($cancelled === 0) {
216 $this->tpl->setOnScreenMessage(
218 $this->lng->txt('no_valid_selection'),
219 true
220 );
221 return null;
222 }
223
224 $this->tpl->setOnScreenMessage(
226 $this->lng->txt('book_reservation_cancelled'),
227 true
228 );
229 return null;
230 }
231
235 private function resolveRowIds(string $key): array
236 {
237 $value = $this->http->get(
238 $key,
239 $this->refinery->custom()->transformation(
240 static function (mixed $raw): array {
241 if ($raw === null || $raw === '') {
242 return [];
243 }
244
245 if (is_array($raw)) {
246 return array_values(array_map('strval', $raw));
247 }
248
249 return [(string) $raw];
250 }
251 )
252 ) ?? [];
253
254 return array_values(array_filter($value, static fn(string $v): bool => $v !== ''));
255 }
256
261 protected function resolveRecords(?array $selected_ids = null): array
262 {
263 $titles = [];
264 foreach (ilBookingObject::getList($this->pool->getId()) as $item) {
265 $titles[(int) $item['booking_object_id']] = (string) $item['title'];
266 }
267
268 if ($selected_ids === null) {
269 $selected_ids = array_map(
270 fn(array $record): string => "{$record['object_id']}_{$record['date_from']}_{$record['date_to']}",
271 $this->bookings
272 );
273 }
274
275 $result = [];
276 $user_id = $this->user->getId();
277 foreach ($selected_ids as $row_id) {
278 $row_id = (string) $row_id;
279 $parts = explode('_', $row_id);
280 $object_id = (int) $parts[0];
281 if ($object_id <= 0 || !isset($titles[$object_id])) {
282 continue;
283 }
284
285 $reservations = ilBookingReservation::getList([$object_id], 1000, 0, []);
286 foreach ($reservations['data'] ?? [] as $reservation) {
287 if ((int) $reservation['user_id'] !== $user_id) {
288 continue;
289 }
290
291 if ((int) $reservation['status'] === ilBookingReservation::STATUS_CANCELLED) {
292 continue;
293 }
294
295 $slot_from = (int) $reservation['date_from'];
296 $slot_to = (int) $reservation['date_to'];
297 if (count($parts) === 3) {
298 if ($slot_from !== (int) $parts[1] || $slot_to !== (int) $parts[2]) {
299 continue;
300 }
301 }
302
303 $result[] = [
304 'reservation_id' => (int) ($reservation['booking_reservation_id'] ?? $reservation['id'] ?? 0),
305 'object_id' => $object_id,
306 'title' => $titles[$object_id],
307 'slot_from' => $slot_from,
308 'slot_to' => $slot_to + 1,
309 'has_schedule' => count($parts) === 3,
310 'has_user_active_booking' =>
311 $user_id === (int) $reservation['user_id']
312 && (int) $reservation['status'] !== ilBookingReservation::STATUS_CANCELLED,
313 ];
314
315 if (count($parts) === 3) {
316 break;
317 }
318 }
319 }
320
321 return $result;
322 }
323
324 private function buildItemDescription(array $record): string
325 {
326 if (!$record['has_schedule']) {
327 return $record['title'];
328 }
329
330 $this->lng->loadLanguageModule('dateplaner');
332 new ilDateTime($record['slot_from'], IL_CAL_UNIX),
333 new ilDateTime($record['slot_to'] - 1, IL_CAL_UNIX)
334 );
335
336 return "{$record['title']} ({$period})";
337 }
338}
onSubmit(URLBuilder $url_builder, array $selected_records, bool $all_records_selected)
onExecute(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token)
__construct(private readonly UIFactory $ui_factory, private readonly UIRenderer $ui_renderer, private readonly ilLanguage $lng, private readonly ilGlobalTemplateInterface $tpl, private readonly HttpService $http, private readonly Refinery $refinery, private readonly AccessManager $access, private readonly ilObjBookingPool $pool, private readonly ilObjUser $user, private readonly int $ref_id, private readonly bool $active_management, private readonly array $bookable_items,)
showModal(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token)
getModal(URLBuilder $url_builder, array $selected_records, bool $all_records_selected)
getTableAction(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token)
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
withParameter(URLBuilderToken $token, string|array $value)
Change an acquired parameter's value if the supplied token is valid.
Definition: URLBuilder.php:166
const IL_CAL_UNIX
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getList(int $a_pool_id, ?string $a_title=null)
Get list of booking objects.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getList(array $a_object_ids, int $a_limit=10, int $a_offset=0, array $filter=[])
List all reservations.
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
language handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
User class.
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This describes commonalities between the different modals.
Definition: Modal.php:35
An entity that renders components to a string output.
Definition: Renderer.php:31
$ref_id
Definition: ltiauth.php:66
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
showModal(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token,)
resolveRecords(?array $selected_ids=null)
trait TableActionModalTrait
@template RecordType
submit(URLBuilder $url_builder, URLBuilderToken $row_id_token, URLBuilderToken $action_token, URLBuilderToken $action_type_token,)
static http()
Fetches the global http state from ILIAS.
modal(string $title="", string $cancel_label="")
global $lng
Definition: privfeed.php:26
if(!file_exists('../ilias.ini.php'))