1<?php
2
3/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5/**
6* Class ilNotification
7*
8* @author Jörg Lützenkirchen <luetzenkirchen@leifos.com>
9* $Id: class.ilObjExerciseGUI.php 24003 2010-05-26 14:35:42Z akill $
10*
11* @ilCtrl_Calls ilNotification:
12*
13* @ingroup ServicesNotification
14*/
15class ilNotification
16{
17    const TYPE_EXERCISE_SUBMISSION = 1;
18    const TYPE_WIKI = 2;
19    const TYPE_WIKI_PAGE = 3;
20    const TYPE_BLOG = 4;
21    const TYPE_DATA_COLLECTION = 5;
22    const TYPE_POLL = 6;
23    const TYPE_LM_BLOCKED_USERS = 7;
24    const TYPE_BOOK = 8;
25    const TYPE_LM = 9;
26    const TYPE_LM_PAGE = 10;
27
28    const THRESHOLD = 180; // time between mails in minutes
29
30    /**
31     * Check notification status for object and user
32     *
33     * @param	int		$type
34     * @param	int		$user_id
35     * @param	int		$id
36     * @return	bool
37     */
38    public static function hasNotification($type, $user_id, $id)
39    {
40        global $DIC;
41
42        $ilDB = $DIC->database();
43        $tree = $DIC->repositoryTree();
44
45        $notification = false;
46
47        include_once("./Services/Notification/classes/class.ilObjNotificationSettings.php");
48        $setting = new ilObjNotificationSettings($id);
49        if ($setting->getMode() != ilObjNotificationSettings::MODE_DEF_OFF_USER_ACTIVATION) {
50            // check membership, members should be notidifed...
51            foreach (ilObject::_getAllReferences($id) as $ref_id) {
52                $grp_ref_id = $tree->checkForParentType($ref_id, 'grp');
53                if ($grp_ref_id > 0) {
54                    include_once("./Modules/Group/classes/class.ilGroupParticipants.php");
55                    if (ilGroupParticipants::_isParticipant($grp_ref_id, $user_id)) {
56                        $notification = true;
57                    }
58                }
59                $crs_ref_id = $tree->checkForParentType($ref_id, 'crs');
60                if ($crs_ref_id > 0) {
61                    include_once("./Modules/Course/classes/class.ilCourseParticipants.php");
62                    if (ilCourseParticipants::_isParticipant($crs_ref_id, $user_id)) {
63                        $notification = true;
64                    }
65                }
66            }
67
68            if ($notification && $setting->getMode() == ilObjNotificationSettings::MODE_DEF_ON_OPT_OUT) {
69                $set = $ilDB->query("SELECT user_id FROM notification" .
70                    " WHERE type = " . $ilDB->quote($type, "integer") .
71                    " AND user_id = " . $ilDB->quote($user_id, "integer") .
72                    " AND id = " . $ilDB->quote($id, "integer") .
73                    " AND activated = " . $ilDB->quote(0, "integer"));
74                $rec = $ilDB->fetchAssoc($set);
75                // ... except when the opted out
76                if ($rec["user_id"] == $user_id) {
77                    return false;
78                }
79                return true;
80            }
81
82            if ($notification && $setting->getMode() == ilObjNotificationSettings::MODE_DEF_ON_NO_OPT_OUT) {
83                return true;
84            }
85        }
86
87
88        $set = $ilDB->query("SELECT user_id FROM notification" .
89            " WHERE type = " . $ilDB->quote($type, "integer") .
90            " AND user_id = " . $ilDB->quote($user_id, "integer") .
91            " AND id = " . $ilDB->quote($id, "integer") .
92            " AND activated = " . $ilDB->quote(1, "integer"));
93
94        return (bool) $ilDB->numRows($set);
95    }
96
97    /**
98     * Is opt out (disable notification) allowed?
99     *
100     * @param	int		$obj_id
101     * @return	bool
102     */
103    public static function hasOptOut($obj_id)
104    {
105        include_once("./Services/Notification/classes/class.ilObjNotificationSettings.php");
106        $setting = new ilObjNotificationSettings($obj_id);
107        if ($setting->getMode() == ilObjNotificationSettings::MODE_DEF_ON_NO_OPT_OUT) {
108            return false;
109        }
110        return true;
111    }
112
113    /**
114     * Get all users for given object
115     *
116     * @param	int		$type
117     * @param	int		$id
118     * @param	int		$page_id
119     * @param	bool	$ignore_threshold
120     * @return	array
121     */
122    public static function getNotificationsForObject($type, $id, $page_id = null, $ignore_threshold = false)
123    {
124        global $DIC;
125
126        $ilDB = $DIC->database();
127        $tree = $DIC->repositoryTree();
128
129        include_once("./Services/Notification/classes/class.ilObjNotificationSettings.php");
130
131        // currently done for blog
132        $recipients = array();
133        $setting = new ilObjNotificationSettings($id);
134        if ($setting->getMode() != ilObjNotificationSettings::MODE_DEF_OFF_USER_ACTIVATION) {
135            foreach (ilObject::_getAllReferences($id) as $ref_id) {
136                $grp_ref_id = $tree->checkForParentType($ref_id, 'grp');
137                if ($grp_ref_id > 0) {
138                    include_once("./Modules/Group/classes/class.ilGroupParticipants.php");
139                    $p = ilGroupParticipants::_getInstanceByObjId(ilObject::_lookupObjectId($grp_ref_id));
140                    foreach ($p->getMembers() as $user_id) {
141                        if (!in_array($user_id, $recipients)) {
142                            $recipients[$user_id] = $user_id;
143                        }
144                    }
145                }
146                $crs_ref_id = $tree->checkForParentType($ref_id, 'crs');
147                if ($crs_ref_id > 0) {
148                    include_once("./Modules/Course/classes/class.ilCourseParticipants.php");
149                    $p = ilCourseParticipants::_getInstanceByObjId(ilObject::_lookupObjectId($crs_ref_id));
150                    foreach ($p->getMembers() as $user_id) {
151                        if (!in_array($user_id, $recipients)) {
152                            $recipients[$user_id] = $user_id;
153                        }
154                    }
155                }
156            }
157        }
158
159        // remove all users that deactivated the feature
160        if ($setting->getMode() == ilObjNotificationSettings::MODE_DEF_ON_OPT_OUT) {
161            $sql = "SELECT user_id FROM notification" .
162                " WHERE type = " . $ilDB->quote($type, "integer") .
163                " AND id = " . $ilDB->quote($id, "integer") .
164                " AND activated = " . $ilDB->quote(0, "integer") .
165                " AND " . $ilDB->in("user_id", $recipients, false, "integer");
166            $set = $ilDB->query($sql);
167            while ($rec = $ilDB->fetchAssoc($set)) {
168                unset($recipients[$rec["user_id"]]);
169            }
170        }
171
172        // remove all users that got a mail
173        if ($setting->getMode() != ilObjNotificationSettings::MODE_DEF_OFF_USER_ACTIVATION && !$ignore_threshold) {
174            $sql = "SELECT user_id FROM notification" .
175                " WHERE type = " . $ilDB->quote($type, "integer") .
176                " AND id = " . $ilDB->quote($id, "integer") .
177                " AND activated = " . $ilDB->quote(1, "integer") .
178                " AND " . $ilDB->in("user_id", $recipients, false, "integer");
179            $sql .= " AND (last_mail > " . $ilDB->quote(date(
180                "Y-m-d H:i:s",
181                strtotime("-" . self::THRESHOLD . "minutes")
182            ), "timestamp");
183            if ($page_id) {
184                $sql .= " AND page_id = " . $ilDB->quote($page_id, "integer");
185            }
186            $sql .= ")";
187
188            $set = $ilDB->query($sql);
189            while ($rec = $ilDB->fetchAssoc($set)) {
190                unset($recipients[$rec["user_id"]]);
191            }
192        }
193
194        // get single subscriptions
195        if ($setting->getMode() != ilObjNotificationSettings::MODE_DEF_ON_NO_OPT_OUT) {
196            $sql = "SELECT user_id FROM notification" .
197                " WHERE type = " . $ilDB->quote($type, "integer") .
198                " AND id = " . $ilDB->quote($id, "integer") .
199                " AND activated = " . $ilDB->quote(1, "integer");
200            if (!$ignore_threshold) {
201                $sql .= " AND (last_mail < " . $ilDB->quote(date(
202                    "Y-m-d H:i:s",
203                    strtotime("-" . self::THRESHOLD . "minutes")
204                ), "timestamp") .
205                    " OR last_mail IS NULL";
206                if ($page_id) {
207                    $sql .= " OR page_id <> " . $ilDB->quote($page_id, "integer");
208                }
209                $sql .= ")";
210            }
211            $set = $ilDB->query($sql);
212            while ($row = $ilDB->fetchAssoc($set)) {
213                $recipients[$row["user_id"]] = $row["user_id"];
214            }
215        }
216
217        return $recipients;
218    }
219
220    /**
221     * Set notification status for object and user
222     *
223     * @param	int		$type
224     * @param	int		$user_id
225     * @param	int		$id
226     * @param	bool	$status
227     */
228    public static function setNotification($type, $user_id, $id, $status = true)
229    {
230        global $DIC;
231
232        $ilDB = $DIC->database();
233
234        $fields = array(
235            "type" => array("integer", $type),
236            "user_id" => array("integer", $user_id),
237            "id" => array("integer", $id)
238        );
239        $ilDB->replace("notification", $fields, array("activated" => array("integer", (int) $status)));
240    }
241
242    /**
243     * Update the last mail timestamp for given object and users
244     *
245     * @param	int		$type
246     * @param	int		$id
247     * @param	array	$user_ids
248     * @param	int		$page_id
249     */
250    public static function updateNotificationTime($type, $id, array $user_ids, $page_id = false)
251    {
252        global $DIC;
253
254        $ilDB = $DIC->database();
255
256        $sql = "UPDATE notification" .
257                " SET last_mail = " . $ilDB->quote(date("Y-m-d H:i:s"), "timestamp");
258
259        if ($page_id) {
260            $sql .= ", page_id = " . $ilDB->quote($page_id, "integer");
261        }
262
263        $sql .= " WHERE type = " . $ilDB->quote($type, "integer") .
264                " AND id = " . $ilDB->quote($id, "integer") .
265                " AND " . $ilDB->in("user_id", $user_ids, false, "integer");
266
267        $ilDB->query($sql);
268    }
269
270    /**
271     * Remove all notifications for given object
272     *
273     * @param	int		$type
274     * @param	int		$id
275     */
276    public static function removeForObject($type, $id)
277    {
278        global $DIC;
279
280        $ilDB = $DIC->database();
281
282        $ilDB->query("DELETE FROM notification" .
283                " WHERE type = " . $ilDB->quote($type, "integer") .
284                " AND id = " . $ilDB->quote($id, "integer"));
285    }
286
287    /**
288     * Remove all notifications for given user
289     *
290     * @param	int		$user_id
291     */
292    public static function removeForUser($user_id)
293    {
294        global $DIC;
295
296        $ilDB = $DIC->database();
297
298        $ilDB->query("DELETE FROM notification" .
299                " WHERE user_id = " . $ilDB->quote($user_id, "integer"));
300    }
301
302    /**
303     * Get activated notifications of give type for user
304     *
305     * @param int $type
306     * @param int $user_id
307     * @return int[]
308     */
309    public static function getActivatedNotifications(int $type, int $user_id) : array
310    {
311        global $DIC;
312
313        $db = $DIC->database();
314
315        $set = $db->queryF(
316            "SELECT id FROM notification " .
317            " WHERE type = %s " .
318            " AND user_id = %s " .
319            " AND activated = %s ",
320            array("integer", "integer", "integer"),
321            array($type, $user_id, 1)
322            );
323        $ids = [];
324        while ($rec = $db->fetchAssoc($set)) {
325            $ids[] = $rec["id"];
326        }
327
328        return $ids;
329    }
330}
331