ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilBookingReservation.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3
13{
17 protected $db;
18
19 protected $id; // int
20 protected $object_id; // int
21 protected $user_id; // int
22 protected $from; // timestamp
23 protected $to; // timestamp
24 protected $status; // status
25 protected $group_id; // int
26 protected $assigner_id; // int
27
31 protected $context_obj_id = 0;
32
33 const STATUS_IN_USE = 2;
35
39 protected $repo;
40
48 public function __construct($a_id = null)
49 {
50 global $DIC;
51
52 $this->db = $DIC->database();
53 $this->id = (int) $a_id;
54
56 $this->repo = $f->getRepo();
57
58 $this->read();
59 }
60
65 public function getId()
66 {
67 return $this->id;
68 }
69
74 public function setObjectId($a_object_id)
75 {
76 $this->object_id = $a_object_id;
77 }
78
83 public function getObjectId()
84 {
85 return $this->object_id;
86 }
87
92 public function setUserId($a_user_id)
93 {
94 $this->user_id = (int) $a_user_id;
95 }
96
101 public function getUserId()
102 {
103 return $this->user_id;
104 }
105
110 public function setAssignerId($a_assigner_id)
111 {
112 $this->assigner_id = (int) $a_assigner_id;
113 }
114
119 public function getAssignerId()
120 {
121 return $this->assigner_id;
122 }
123
128 public function setFrom($a_from)
129 {
130 $this->from = (int) $a_from;
131 }
132
137 public function getFrom()
138 {
139 return $this->from;
140 }
141
146 public function setTo($a_to)
147 {
148 $this->to = (int) $a_to;
149 }
150
155 public function getTo()
156 {
157 return $this->to;
158 }
159
164 public function setStatus($a_status)
165 {
166 if ($a_status === null) {
167 $this->status = null;
168 }
169 if ($this->isValidStatus((int) $a_status)) {
170 $this->status = (int) $a_status;
171 }
172 }
173
178 public function getStatus()
179 {
180 return $this->status;
181 }
182
188 public static function isValidStatus($a_status)
189 {
190 if (in_array($a_status, array(self::STATUS_IN_USE, self::STATUS_CANCELLED))) {
191 return true;
192 }
193 return false;
194 }
195
200 public function setGroupId($a_group_id)
201 {
202 $this->group_id = $a_group_id;
203 }
204
209 public function getGroupId()
210 {
211 return $this->group_id;
212 }
213
219 public function setContextObjId($a_val)
220 {
221 $this->context_obj_id = $a_val;
222 }
223
229 public function getContextObjId()
230 {
232 }
233
234
238 protected function read()
239 {
240 if ($this->id) {
241 $row = $this->repo->getForId($this->id);
242 $this->setUserId($row['user_id']);
243 $this->setAssignerId($row['assigner_id']);
244 $this->setObjectId($row['object_id']);
245 $this->setFrom($row['date_from']);
246 $this->setTo($row['date_to']);
247 $this->setStatus($row['status']);
248 $this->setGroupId($row['group_id']);
249 $this->setContextObjId($row['context_obj_id']);
250 }
251 }
252
257 public function save()
258 {
259 if ($this->id) {
260 return false;
261 }
262
263 $this->id = $this->repo->create(
264 $this->getUserId(),
265 $this->getAssignerId(),
266 $this->getObjectId(),
267 $this->getContextObjId(),
268 $this->getFrom(),
269 $this->getTo(),
270 $this->getStatus(),
271 $this->getGroupId()
272 );
273 return ($this->id > 0);
274 }
275
279 public function update()
280 {
281 if (!$this->id) {
282 return false;
283 }
284
285 $this->repo->update(
286 $this->id,
287 $this->getUserId(),
288 $this->getAssignerId(),
289 $this->getObjectId(),
290 $this->getContextObjId(),
291 $this->getFrom(),
292 $this->getTo(),
293 $this->getStatus(),
294 $this->getGroupId()
295 );
296 return true;
297 }
298
302 public function delete()
303 {
304 $this->repo->delete($this->id);
305 }
306
307
316 public static function getAvailableObject(array $a_ids, $a_from, $a_to, $a_return_single = true, $a_return_counter = false)
317 {
319
321 $repo = $f->getRepo();
322
323 $blocked = $counter = array();
324 foreach ($repo->getNumberOfReservations($a_ids, $a_from, $a_to) as $row) {
325 if ($row['cnt'] >= $nr_map[$row['object_id']]) {
326 $blocked[] = $row['object_id'];
327 } elseif ($a_return_counter) {
328 $counter[$row['object_id']] = (int) $nr_map[$row['object_id']] - (int) $row['cnt'];
329 }
330 }
331
332 // #17868 - validate against schedule availability
333 foreach ($a_ids as $obj_id) {
334 $bobj = new ilBookingObject($obj_id);
335 if ($bobj->getScheduleId()) {
336 $schedule = new ilBookingSchedule($bobj->getScheduleId());
337
338 $av_from = ($schedule->getAvailabilityFrom() && !$schedule->getAvailabilityFrom()->isNull())
339 ? $schedule->getAvailabilityFrom()->get(IL_CAL_UNIX)
340 : null;
341 $av_to = ($schedule->getAvailabilityTo() && !$schedule->getAvailabilityTo()->isNull())
342 ? strtotime($schedule->getAvailabilityTo()->get(IL_CAL_DATE) . " 23:59:59")
343 : null;
344
345 if (($av_from && $a_from < $av_from) ||
346 ($av_to && $a_to > $av_to)) {
347 $blocked[] = $obj_id;
348 unset($counter[$obj_id]);
349 }
350 }
351 }
352
353 $available = array_diff($a_ids, $blocked);
354 if (sizeof($available)) {
355 if ($a_return_counter) {
356 foreach ($a_ids as $id) {
357 if (!isset($counter[$id])) {
358 $counter[$id] = (int) $nr_map[$id];
359 }
360 }
361 return $counter;
362 } elseif ($a_return_single) {
363 return array_shift($available);
364 } else {
365 return $available;
366 }
367 }
368 }
369
370 public static function isObjectAvailableInPeriod($a_obj_id, ilBookingSchedule $a_schedule, $a_from, $a_to)
371 {
372 global $DIC;
373
374 $ilDB = $DIC->database();
375
376 if (!$a_from) {
377 $a_from = time();
378 }
379 if (!$a_to) {
380 $a_to = strtotime("+1year", $a_from);
381 }
382
383 if ($a_from > $a_to) {
384 return;
385 }
386
387 // all nr of reservations in period that are not over yet (to >= now)
389 $repo = $f->getRepo();
390 $res = $repo->getNumberOfReservations([$a_obj_id], $a_from, $a_to, true);
391 $booked_in_period = (int) $res[$a_obj_id]["cnt"];
392
393 $per_slot = ilBookingObject::getNrOfItemsForObjects(array($a_obj_id));
394 $per_slot = $per_slot[$a_obj_id];
395
396 // max available nr of items per (week)day
397 $schedule_slots = array();
398 $definition = $a_schedule->getDefinition();
399 $map = array_flip(array("su", "mo", "tu", "we", "th", "fr", "sa"));
400 foreach ($definition as $day => $day_slots) {
401 $schedule_slots[$map[$day]] = $day_slots;
402 }
403
404 $av_from = ($a_schedule->getAvailabilityFrom() && !$a_schedule->getAvailabilityFrom()->isNull())
405 ? $a_schedule->getAvailabilityFrom()->get(IL_CAL_UNIX)
406 : null;
407 $av_to = ($a_schedule->getAvailabilityTo() && !$a_schedule->getAvailabilityTo()->isNull())
408 ? strtotime($a_schedule->getAvailabilityTo()->get(IL_CAL_DATE) . " 23:59:59")
409 : null;
410
411 // sum up max available (to >= now) items in period per (week)day
412 $available_in_period = 0;
413 $loop = 0;
414 while ($a_from < $a_to &&
415 ++$loop < 1000) {
416 // any slots for current weekday?
417 $day_slots = $schedule_slots[date("w", $a_from)];
418 if ($day_slots) {
419 foreach ($day_slots as $slot) {
420 // convert slot to current datetime
421 $slot = explode("-", $slot);
422 $slot_from = strtotime(date("Y-m-d", $a_from) . " " . $slot[0]);
423 $slot_to = strtotime(date("Y-m-d", $a_from) . " " . $slot[1]);
424 // slot has to be in the future and part of schedule availability
425 if ($slot_to > time() &&
426 $slot_from >= $av_from &&
427 ($slot_to <= $av_to || is_null($av_to))) {
428 $available_in_period += $per_slot;
429 }
430 }
431 }
432
433 $a_from += (60 * 60 * 24);
434 }
435 if ($available_in_period - $booked_in_period > 0) {
436 return true;
437 }
438
439 return false;
440 }
441
442 //check if the user reached the limit of bookings in this booking pool.
443 public static function isBookingPoolLimitReachedByUser(int $a_user_id, int $a_pool_id) : int
444 {
445 global $DIC;
446 $ilDB = $DIC->database();
447
448 $booking_pool_objects = ilBookingObject::getObjectsForPool($a_pool_id);
449
450 $query = "SELECT count(user_id) total" .
451 " FROM booking_reservation" .
452 " WHERE " . $ilDB->in('object_id', $booking_pool_objects, false, 'integer') .
453 " AND user_id = " . $a_user_id .
454 " AND (status IS NULL OR status <> " . ilBookingReservation::STATUS_CANCELLED . ')';
455 $res = $ilDB->query($query);
456 $row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC);
457
458 return (int) $row['total'];
459 }
460
461 public static function getMembersWithoutReservation(int $a_object_id) : array
462 {
463 global $DIC;
464 $ilDB = $DIC->database();
465
466 $pool_id = ilBookingObject::lookupPoolId($a_object_id);
467
468 $res = array();
469 $query = 'SELECT DISTINCT bm.user_id user_id' .
470 ' FROM booking_member bm' .
471 ' WHERE bm.booking_pool_id = ' . $ilDB->quote($pool_id, 'integer') .
472 ' AND bm.user_id NOT IN (' .
473 'SELECT user_id' .
474 ' FROM booking_reservation' .
475 ' WHERE object_id = ' . $ilDB->quote($a_object_id, 'integer') .
476 ' AND (status IS NULL OR status <> ' . ilBookingReservation::STATUS_CANCELLED . '))';
477
478 $set = $ilDB->query($query);
479
480 while ($row = $ilDB->fetchAssoc($set)) {
481 $res[] = $row['user_id'];
482 }
483
484 return $res;
485 }
486
487 public static function isObjectAvailableNoSchedule($a_obj_id)
488 {
489 $available = self::getNumAvailablesNoSchedule($a_obj_id);
490 return (bool) $available; // #11864
491 }
492 public static function numAvailableFromObjectNoSchedule($a_obj_id)
493 {
494 $available = self::getNumAvailablesNoSchedule($a_obj_id);
495 return (int) $available;
496 }
497
498 public static function getNumAvailablesNoSchedule($a_obj_id)
499 {
500 global $DIC;
501
502 $ilDB = $DIC->database();
503
504 $all = ilBookingObject::getNrOfItemsForObjects(array($a_obj_id));
505 $all = (int) $all[$a_obj_id];
506
507 $set = $ilDB->query('SELECT COUNT(*) cnt' .
508 ' FROM booking_reservation r' .
509 ' JOIN booking_object o ON (o.booking_object_id = r.object_id)' .
510 ' WHERE (status IS NULL OR status <> ' . $ilDB->quote(self::STATUS_CANCELLED, 'integer') . ')' .
511 ' AND r.object_id = ' . $ilDB->quote($a_obj_id, 'integer'));
512 $cnt = $ilDB->fetchAssoc($set);
513 $cnt = (int) $cnt['cnt'];
514
515 return (int) $all - $cnt; // #11864
516 }
517
523 public static function getCurrentOrUpcomingReservation($a_object_id)
524 {
525 global $DIC;
526
527 $ilDB = $DIC->database();
528
529 $now = $ilDB->quote(time(), 'integer');
530
531 $ilDB->setLimit(1);
532 $set = $ilDB->query('SELECT user_id, status, date_from, date_to' .
533 ' FROM booking_reservation' .
534 ' WHERE ((date_from <= ' . $now . ' AND date_to >= ' . $now . ')' .
535 ' OR date_from > ' . $now . ')' .
536 ' AND (status <> ' . $ilDB->quote(self::STATUS_CANCELLED, 'integer') .
537 ' OR STATUS IS NULL) AND object_id = ' . $ilDB->quote($a_object_id, 'integer') .
538 ' ORDER BY date_from');
539 $row = $ilDB->fetchAssoc($set);
540 return $row;
541 }
542
543 public static function getObjectReservationForUser($a_object_id, $a_user_id, $a_multi = false)
544 {
545 global $DIC;
546
547 $ilDB = $DIC->database();
548
549 $set = $ilDB->query('SELECT booking_reservation_id FROM booking_reservation' .
550 ' WHERE user_id = ' . $ilDB->quote($a_user_id, 'integer') .
551 ' AND object_id = ' . $ilDB->quote($a_object_id, 'integer') .
552 ' AND (status <> ' . $ilDB->quote(self::STATUS_CANCELLED, 'integer') .
553 ' OR STATUS IS NULL)');
554 if (!$a_multi) {
555 $row = $ilDB->fetchAssoc($set);
556 return $row['booking_reservation_id'];
557 } else {
558 $res = array();
559 while ($row = $ilDB->fetchAssoc($set)) {
560 $res[] = $row['booking_reservation_id'];
561 }
562 return $res;
563 }
564 }
565
574 public static function getList($a_object_ids, $a_limit = 10, $a_offset = 0, array $filter = [])
575 {
576 global $DIC;
577
578 $ilDB = $DIC->database();
579
580 $sql = 'SELECT r.*,o.title' .
581 ' FROM booking_reservation r' .
582 ' JOIN booking_object o ON (o.booking_object_id = r.object_id)';
583
584 $count_sql = 'SELECT COUNT(*) AS counter' .
585 ' FROM booking_reservation r' .
586 ' JOIN booking_object o ON (o.booking_object_id = r.object_id)';
587
588 $where = array($ilDB->in('r.object_id', $a_object_ids, '', 'integer'));
589 if ($filter['status']) {
590 if ($filter['status'] > 0) {
591 $where[] = 'status = ' . $ilDB->quote($filter['status'], 'integer');
592 } else {
593 $where[] = '(status != ' . $ilDB->quote(-$filter['status'], 'integer') .
594 ' OR status IS NULL)';
595 }
596 }
597 if ($filter['from']) {
598 $where[] = 'date_from >= ' . $ilDB->quote($filter['from'], 'integer');
599 }
600 if ($filter['to']) {
601 $where[] = 'date_to <= ' . $ilDB->quote($filter['to'], 'integer');
602 }
603 if (sizeof($where)) {
604 $sql .= ' WHERE ' . implode(' AND ', $where);
605 $count_sql .= ' WHERE ' . implode(' AND ', $where);
606 }
607
608 $set = $ilDB->query($count_sql);
609 $row = $ilDB->fetchAssoc($set);
610 $counter = $row['counter'];
611
612 $sql .= ' ORDER BY date_from DESC, booking_reservation_id DESC';
613
614 $ilDB->setLimit($a_limit, $a_offset);
615 $set = $ilDB->query($sql);
616 $res = array();
617 while ($row = $ilDB->fetchAssoc($set)) {
618 $res[] = $row;
619 }
620
621 return array('data' => $res, 'counter' => $counter);
622 }
623
624
631 public static function getUserFilter(array $a_object_ids)
632 {
633 global $DIC;
634
635 $ilDB = $DIC->database();
636
637 $res = array();
638
639 $sql = "SELECT ud.usr_id,ud.lastname,ud.firstname,ud.login" .
640 " FROM usr_data ud " .
641 " LEFT JOIN booking_reservation r ON (r.user_id = ud.usr_id)" .
642 " WHERE ud.usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer") .
643 " AND " . $ilDB->in("r.object_id", $a_object_ids, "", "integer") .
644 " ORDER BY ud.lastname,ud.firstname";
645 $set = $ilDB->query($sql);
646 while ($row = $ilDB->fetchAssoc($set)) {
647 $res[$row["usr_id"]] = $row["lastname"] . ", " . $row["firstname"] .
648 " (" . $row["login"] . ")";
649 }
650
651 return $res;
652 }
653
654
661 public static function changeStatus(array $a_ids, $a_status)
662 {
663 global $DIC;
664
665 $ilDB = $DIC->database();
666
667 if (self::isValidStatus($a_status)) {
668 return $ilDB->manipulate('UPDATE booking_reservation' .
669 ' SET status = ' . $ilDB->quote($a_status, 'integer') .
670 ' WHERE ' . $ilDB->in('booking_reservation_id', $a_ids, '', 'integer'));
671 }
672 }
673
674 public function getCalendarEntry()
675 {
677
678
679 $set = $ilDB->query("SELECT ce.cal_id FROM cal_entries ce" .
680 " JOIN cal_cat_assignments cca ON ce.cal_id = cca.cal_id" .
681 " JOIN cal_categories cc ON cca.cat_id = cc.cat_id" .
682 " JOIN booking_reservation br ON ce.context_id = br.booking_reservation_id" .
683 " WHERE cc.obj_id = " . $ilDB->quote($this->getUserId(), 'integer') .
684 " AND br.user_id = " . $ilDB->quote($this->getUserId(), 'integer') .
685 " AND cc.type = " . $ilDB->quote(ilCalendarCategory::TYPE_BOOK, 'integer') .
686 " AND ce.context_id = " . $ilDB->quote($this->getId(), 'integer'));
687 $row = $ilDB->fetchAssoc($set);
688 return $row["cal_id"];
689 }
690
700 public static function getCancelDetails($a_obj_id, $a_user_id, $a_from, $a_to)
701 {
702 global $DIC;
703
704 $ilDB = $DIC->database();
705
706 $res = array();
707
708 $sql = "SELECT booking_reservation_id" .
709 " FROM booking_reservation" .
710 " WHERE object_id = " . $ilDB->quote($a_obj_id, "integer") .
711 " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
712 " AND date_from = " . $ilDB->quote($a_from, "integer") .
713 " AND date_to = " . $ilDB->quote($a_to, "integer") .
714 " AND (status IS NULL" .
715 " OR status <> " . $ilDB->quote(self::STATUS_CANCELLED, "integer") . ")";
716 $set = $ilDB->query($sql);
717 while ($row = $ilDB->fetchAssoc($set)) {
718 $res[] = $row["booking_reservation_id"];
719 }
720
721 return $res;
722 }
723}
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_DATE
const IL_CAL_UNIX
a bookable ressource
static lookupPoolId($object_id)
Lookup pool id.
static getNrOfItemsForObjects(array $a_obj_ids)
Get nr of available items.
static getObjectsForPool(int $a_pool_id)
Get all booking pool object ids from an specific booking pool.
getFrom()
Get booking from date.
static getObjectReservationForUser($a_object_id, $a_user_id, $a_multi=false)
getContextObjId()
Get context object id.
static getCurrentOrUpcomingReservation($a_object_id)
Get details about object reservation.
getUserId()
Get booking user id.
setTo($a_to)
Set booking to date.
static changeStatus(array $a_ids, $a_status)
Batch update reservation status.
setObjectId($a_object_id)
Set object id.
setAssignerId($a_assigner_id)
Set assigner user id.
setFrom($a_from)
Set booking from date.
setGroupId($a_group_id)
Set group id.
static getAvailableObject(array $a_ids, $a_from, $a_to, $a_return_single=true, $a_return_counter=false)
Check if any of given objects are bookable.
setContextObjId($a_val)
Set context object id.
static isBookingPoolLimitReachedByUser(int $a_user_id, int $a_pool_id)
__construct($a_id=null)
Constructor.
setStatus($a_status)
Set booking status.
static getMembersWithoutReservation(int $a_object_id)
static isObjectAvailableInPeriod($a_obj_id, ilBookingSchedule $a_schedule, $a_from, $a_to)
static isValidStatus($a_status)
Check if given status is valid.
static getNumAvailablesNoSchedule($a_obj_id)
static getCancelDetails($a_obj_id, $a_user_id, $a_from, $a_to)
Get reservation ids from aggregated id for cancellation.
save()
Create new entry in db.
static getUserFilter(array $a_object_ids)
Get all users who have reservations for object(s)
setUserId($a_user_id)
Set booking user id.
static numAvailableFromObjectNoSchedule($a_obj_id)
static isObjectAvailableNoSchedule($a_obj_id)
static getList($a_object_ids, $a_limit=10, $a_offset=0, array $filter=[])
List all reservations.
getAssignerId()
Get assigner user id.
schedule for booking ressource
getAvailabilityTo()
Get availability end.
getAvailabilityFrom()
Get availability start.
getDefinition()
Get definition.
$query
foreach($_POST as $key=> $value) $res
global $ilDB
$DIC
Definition: xapitoken.php:46