1<?php
2/* Copyright (c) 1998-2018 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4/**
5 * Class ilBookingParticipant
6 *
7 * @author Jesús López <lopez@leifos.com>
8 */
9class ilBookingParticipant
10{
11    protected $lng;
12    protected $db;
13    protected $participant_id;
14    protected $booking_pool_id;
15    protected $is_new;
16
17    /**
18     * ilBookingParticipant constructor.
19     * @param $a_user_id integer
20     * @param $a_booking_pool_id integer
21     */
22    public function __construct($a_user_id, $a_booking_pool_id)
23    {
24        if (!ilObjUser::_exists($a_user_id) || !ilObjBookingPool::_exists($a_booking_pool_id)) {
25            return false;
26        }
27
28        global $DIC;
29        $this->lng = $DIC->language();
30        $this->db = $DIC->database();
31        $this->il_user = $DIC->user();
32
33        $this->participant_id = $a_user_id;
34        $this->booking_pool_id = $a_booking_pool_id;
35
36        // if read and not exists, store it in db.
37        if (!$this->read()) {
38            $this->save();
39            $this->is_new = true;
40        } else {
41            $this->is_new = false;
42        }
43    }
44
45    /**
46     * Read from DB
47     * @return int|bool participant id if found.
48     */
49    protected function read()
50    {
51        $query = 'SELECT participant_id FROM booking_member' .
52            ' WHERE user_id = ' . $this->db->quote($this->participant_id, 'integer') .
53            ' AND booking_pool_id = ' . $this->db->quote($this->booking_pool_id, 'integer');
54
55        $set = $this->db->query($query);
56        $row = $this->db->fetchAssoc($set);
57        if (empty($row)) {
58            return false;
59        } else {
60            return $row['participant_id'];
61        }
62    }
63
64    /**
65     * Save booking participant in DB
66     */
67    protected function save()
68    {
69        $assigner_id = $this->il_user->getId();
70        $next_id = $this->db->nextId('booking_member');
71
72        $query = 'INSERT INTO booking_member' .
73            ' (participant_id, user_id, booking_pool_id, assigner_user_id)' .
74            ' VALUES (' . $this->db->quote($next_id, 'integer') .
75            ',' . $this->db->quote($this->participant_id, 'integer') .
76            ',' . $this->db->quote($this->booking_pool_id, 'integer') .
77            ',' . $this->db->quote($assigner_id, 'integer') . ')';
78
79        $this->db->manipulate($query);
80    }
81
82    /**
83     * @return bool IF read or created
84     */
85    public function getIsNew()
86    {
87        return $this->is_new;
88    }
89
90    /**
91     * Get participants who can not have a reservation for this booking pool object id.
92     *
93     * @param integer $a_bp_object_id booking pool object
94     * @return array formatted data to display in gui table.
95     */
96    public static function getAssignableParticipants($a_bp_object_id)
97    {
98        $booking_object = new ilBookingObject($a_bp_object_id);
99        $pool_id = $booking_object->getPoolId();
100        $pool = new ilObjBookingPool($pool_id, false);
101        $overall_limit = (int) $pool->getOverallLimit();
102
103        $res = array();
104
105        $members = ilBookingReservation::getMembersWithoutReservation($a_bp_object_id);
106
107        foreach ($members as $member_id) {
108            //check if the user reached the limit of booking in this booking pool.
109            $total_reservations = ilBookingReservation::isBookingPoolLimitReachedByUser($member_id, $pool_id);
110
111            if ($overall_limit == 0 || ($overall_limit > 0 && $total_reservations < $overall_limit)) {
112                $user_name = ilObjUser::_lookupName($member_id);
113                $name = $user_name['lastname'] . ", " . $user_name['firstname'];
114                $index = $a_bp_object_id . "_" . $member_id;
115
116                if (!isset($res[$index])) {
117                    $res[$index] = array(
118                        "user_id" => $member_id,
119                        "object_title" => array($booking_object->getTitle()),
120                        "name" => $name
121                    );
122                } else {
123                    if (!in_array($booking_object->getTitle(), $res[$index]['object_title'])) {
124                        array_push($res[$index]['object_title'], $booking_object->getTitle());
125                    }
126                }
127            }
128        }
129
130        return $res;
131    }
132
133    public static function getList($a_booking_pool, array $a_filter = null, $a_object_id = null)
134    {
135        global $DIC;
136
137        $ilDB = $DIC->database();
138        $lng = $DIC->language();
139        $ctrl = $DIC->ctrl();
140
141        $res = array();
142
143        $query = 'SELECT bm.user_id, bm.booking_pool_id, br.object_id, bo.title, br.status' .
144            ' FROM booking_member bm' .
145            ' LEFT JOIN booking_reservation br ON (bm.user_id = br.user_id)' .
146            ' LEFT JOIN booking_object bo ON (br.object_id = bo.booking_object_id AND bo.pool_id = ' . $ilDB->quote($a_booking_pool, 'integer') . ')';
147
148        $where = array('bm.booking_pool_id =' . $ilDB->quote($a_booking_pool, 'integer'));
149        if ($a_object_id) {
150            $where[] = 'br.object_id = ' . $ilDB->quote($a_object_id, 'integer');
151        }
152        if ($a_filter['title']) {
153            $where[] = '(' . $ilDB->like('title', 'text', '%' . $a_filter['title'] . '%') .
154                ' OR ' . $ilDB->like('description', 'text', '%' . $a_filter['title'] . '%') . ')';
155        }
156        if ($a_filter['user_id']) {
157            $where[] = 'bm.user_id = ' . $ilDB->quote($a_filter['user_id'], 'integer');
158        }
159
160        $query .= ' WHERE ' . implode(' AND ', $where);
161
162        $set = $ilDB->query($query);
163
164        while ($row = $ilDB->fetchAssoc($set)) {
165            $status = $row['status'];
166            //Nothing to show if the status is canceled when filtering by object
167            if ($status == ilBookingReservation::STATUS_CANCELLED && $a_object_id) {
168                continue;
169            }
170
171            $user_name = ilObjUser::_lookupName($row['user_id']);
172            $name = $user_name['lastname'] . ", " . $user_name['firstname'];
173            $index = $a_booking_pool . "_" . $row['user_id'];
174            $actions = array();
175
176            if (!isset($res[$index])) {
177                $res[$index] = array(
178                    "object_title" => array(),
179                    "name" => $name
180                );
181
182                if ($status != ilBookingReservation::STATUS_CANCELLED && $row['title'] != "") {
183                    $res[$index]['object_title'] = array($row['title']);
184                    $res[$index]['obj_count'] = 1;
185                    $res[$index]['object_ids'][] = $row['object_id'];
186                }
187            } else {
188                if ($row['title'] != "" && (!in_array(
189                    $row['title'],
190                    $res[$index]['object_title']
191                ) && $status != ilBookingReservation::STATUS_CANCELLED)) {
192                    array_push($res[$index]['object_title'], $row['title']);
193                    $res[$index]['obj_count'] = $res[$index]['obj_count'] + 1;
194                    $res[$index]['object_ids'][] = $row['object_id'];
195                }
196            }
197            $res[$index]['user_id'] = $row['user_id'];
198        }
199
200        $bp = new ilObjBookingPool($a_booking_pool, false);
201
202        foreach ($res as $index => $val) {
203            $actions = [];
204            // action assign only if user did not booked all objects.
205            //if($res[$index]['obj_count'] < ilBookingObject::getNumberOfObjectsForPool($a_booking_pool))
206
207            // alex: this does not seem to be correct: assignments are always possible for all objects
208            $has_schedule = ($bp->getScheduleType() == ilObjBookingPool::TYPE_FIX_SCHEDULE);
209            $limit_reached = (!$has_schedule && $bp->getOverallLimit() <= $val['obj_count']);
210            if (!$limit_reached) {
211                $ctrl->setParameterByClass('ilbookingparticipantgui', 'bkusr', $val['user_id']);
212                $actions[] = array(
213                    'text' => $lng->txt("book_assign_object"),
214                    'url' => $ctrl->getLinkTargetByClass("ilbookingparticipantgui", 'assignObjects')
215                );
216                $ctrl->setParameterByClass('ilbookingparticipantgui', 'bkusr', '');
217            }
218
219
220            if ($bp->getScheduleType() == ilObjBookingPool::TYPE_NO_SCHEDULE && $val['obj_count'] == 1) {
221                $ctrl->setParameterByClass('ilbookingobjectgui', 'bkusr', $val['user_id']);
222                $ctrl->setParameterByClass('ilbookingobjectgui', 'object_id', $val['object_ids'][0]);
223                $ctrl->setParameterByClass('ilbookingobjectgui', 'part_view', ilBookingParticipantGUI::PARTICIPANT_VIEW);
224
225                $actions[] = array(
226                    'text' => $lng->txt("book_deassign"),
227                    'url' => $ctrl->getLinkTargetByClass("ilbookingobjectgui", 'rsvConfirmCancelUser')
228                );
229
230                $ctrl->setParameterByClass('ilbookingparticipantgui', 'bkusr', '');
231                $ctrl->setParameterByClass('ilbookingparticipantgui', 'object_id', '');
232                $ctrl->setParameterByClass('ilbookingobjectgui', 'part_view', '');
233            } elseif ($bp->getScheduleType() == ilObjBookingPool::TYPE_FIX_SCHEDULE || $res[$index]['obj_count'] > 1) {
234                $ctrl->setParameterByClass('ilobjbookingpoolgui', 'user_id', $val['user_id']);
235                $actions[] = array(
236                    'text' => $lng->txt("book_deassign"),
237                    'url' => $ctrl->getLinkTargetByClass("ilobjbookingpoolgui", 'log')
238                );
239                $ctrl->setParameterByClass('ilobjbookingpoolgui', 'user_id', '');
240            }
241
242            //add the actions
243            $res[$index]['actions'] = $actions;
244        }
245        //echo "<pre>"; print_r($res); exit;
246        return $res;
247    }
248
249    /**
250     * Get all participants for a booking pool.
251     * @param $a_booking_pool_id
252     * @return array
253     */
254    public static function getBookingPoolParticipants(integer $a_booking_pool_id) : array
255    {
256        global $DIC;
257        $ilDB = $DIC->database();
258        $sql = 'SELECT * FROM booking_member WHERE booking_pool_id = ' . $ilDB->quote($a_booking_pool_id, 'integer');
259
260        $set = $ilDB->query($sql);
261
262        $res = array();
263        while ($row = $ilDB->fetchAssoc($set)) {
264            $res[] = $row['user_id'];
265        }
266
267        return $res;
268    }
269
270    /**
271     *Get user data from db for an specific pool id.
272     *
273     * @param integer $a_pool_id
274     * @return array
275     */
276    public static function getUserFilter($a_pool_id)
277    {
278        global $DIC;
279
280        $ilDB = $DIC->database();
281
282        $res = array();
283
284        $sql = "SELECT ud.usr_id,ud.lastname,ud.firstname,ud.login" .
285            " FROM usr_data ud " .
286            " RIGHT JOIN booking_member m ON (ud.usr_id = m.user_id)" .
287            " WHERE ud.usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer") .
288            " AND m.booking_pool_id = " . $ilDB->quote($a_pool_id, "integer") .
289            " ORDER BY ud.lastname,ud.firstname";
290
291        $set = $ilDB->query($sql);
292        while ($row = $ilDB->fetchAssoc($set)) {
293            $res[$row["usr_id"]] = $row["lastname"] . ", " . $row["firstname"] .
294                " (" . $row["login"] . ")";
295        }
296
297        return $res;
298    }
299
300    /**
301     * Returns true if the participant has a reservation for this object.
302     * @param $a_booking_object_id
303     * @param $a_participant_id
304     * @return bool
305     */
306    protected function isParticipantAssigned($a_booking_object_id, $a_participant_id)
307    {
308        if (!empty(ilBookingReservation::getObjectReservationForUser($a_booking_object_id, $a_participant_id))) {
309            return true;
310        } else {
311            return false;
312        }
313    }
314}
315