99003d62371863a9d6898e26d40457a307db13fc
[moodle.git] / admin / tool / monitor / classes / subscription_manager.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Class to manage subscriptions.
19  *
20  * @package    tool_monitor
21  * @copyright  2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace tool_monitor;
27 defined('MOODLE_INTERNAL') || die();
29 /**
30  * Class to manage subscriptions.
31  *
32  * @since      Moodle 2.8
33  * @package    tool_monitor
34  * @copyright  2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
35  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class subscription_manager {
38     /**
39      * Subscribe a user to a given rule.
40      *
41      * @param int $ruleid  Rule id.
42      * @param int $courseid Course id.
43      * @param int $cmid Course module id.
44      * @param int $userid User who is subscribing, defaults to $USER.
45      *
46      * @return bool|int returns id of the created subscription.
47      */
48     public static function create_subscription($ruleid, $courseid, $cmid, $userid = 0) {
49         global $DB, $USER;
51         $subscription = new \stdClass();
52         $subscription->ruleid = $ruleid;
53         $subscription->courseid = $courseid;
54         $subscription->cmid = $cmid;
55         $subscription->userid = empty($userid) ? $USER->id : $userid;
56         if ($DB->record_exists('tool_monitor_subscriptions', (array)$subscription)) {
57             // Subscription already exists.
58             return false;
59         }
61         $subscription->timecreated = time();
62         $subscription->id = $DB->insert_record('tool_monitor_subscriptions', $subscription);
64         // Trigger a subscription created event.
65         if ($subscription->id) {
66             if (!empty($subscription->courseid)) {
67                 $courseid = $subscription->courseid;
68                 $context = \context_course::instance($subscription->courseid);
69             } else {
70                 $courseid = 0;
71                 $context = \context_system::instance();
72             }
74             $params = array(
75                 'objectid' => $subscription->id,
76                 'courseid' => $courseid,
77                 'context' => $context
78             );
79             $event = \tool_monitor\event\subscription_created::create($params);
80             $event->trigger();
81         }
83         return $subscription->id;
84     }
86     /**
87      * Delete a subscription.
88      *
89      * @param subscription|int $subscriptionorid an instance of subscription class or id.
90      * @param bool $checkuser Check if the subscription belongs to current user before deleting.
91      *
92      * @return bool
93      * @throws \coding_exception if $checkuser is true and the subscription doesn't belong to the current user.
94      */
95     public static function delete_subscription($subscriptionorid, $checkuser = true) {
96         global $DB, $USER;
97         if (is_object($subscriptionorid)) {
98             $subscription = $subscriptionorid;
99         } else {
100             $subscription = self::get_subscription($subscriptionorid);
101         }
102         if ($checkuser && $subscription->userid != $USER->id) {
103             throw new \coding_exception('Invalid subscription supplied');
104         }
106         // Store the subscription before we delete it.
107         $subscription = $DB->get_record('tool_monitor_subscriptions', array('id' => $subscription->id));
109         $success = $DB->delete_records('tool_monitor_subscriptions', array('id' => $subscription->id));
111         // If successful trigger a subscription_deleted event.
112         if ($success) {
113             if (!empty($subscription->courseid)) {
114                 $courseid = $subscription->courseid;
115                 $context = \context_course::instance($subscription->courseid);
116             } else {
117                 $courseid = 0;
118                 $context = \context_system::instance();
119             }
121             $params = array(
122                 'objectid' => $subscription->id,
123                 'courseid' => $courseid,
124                 'context' => $context
125             );
126             $event = \tool_monitor\event\subscription_deleted::create($params);
127             $event->add_record_snapshot('tool_monitor_subscriptions', $subscription);
128             $event->trigger();
129         }
131         return $success;
132     }
134     /**
135      * Delete all subscriptions for a user.
136      *
137      * @param int $userid user id.
138      *
139      * @return mixed
140      */
141     public static function delete_user_subscriptions($userid) {
142         global $DB;
143         return $DB->delete_records('tool_monitor_subscriptions', array('userid' => $userid));
144     }
146     /**
147      * Delete all subscriptions for a course module.
148      *
149      * @param int $cmid cm id.
150      *
151      * @return mixed
152      */
153     public static function delete_cm_subscriptions($cmid) {
154         global $DB;
155         return $DB->delete_records('tool_monitor_subscriptions', array('cmid' => $cmid));
156     }
158     /**
159      * Delete all subscribers for a given rule.
160      *
161      * @param int $ruleid rule id.
162      * @param \context|null $coursecontext the context of the course - this is passed when we
163      *      can not get the context via \context_course as the course has been deleted.
164      *
165      * @return bool
166      */
167     public static function remove_all_subscriptions_for_rule($ruleid, $coursecontext = null) {
168         global $DB;
170         // Store all the subscriptions we have to delete.
171         $subscriptions = $DB->get_recordset('tool_monitor_subscriptions', array('ruleid' => $ruleid));
173         // Now delete them.
174         $success = $DB->delete_records('tool_monitor_subscriptions', array('ruleid' => $ruleid));
176         // If successful and there were subscriptions that were deleted trigger a subscription deleted event.
177         if ($success && $subscriptions) {
178             foreach ($subscriptions as $subscription) {
179                 // It is possible that we are deleting rules associated with a deleted course, so we should be
180                 // passing the context as the second parameter.
181                 if (!is_null($coursecontext)) {
182                     $context = $coursecontext;
183                     $courseid = $subscription->courseid;
184                 } else if (!empty($subscription->courseid) && ($coursecontext =
185                         \context_course::instance($subscription->courseid, IGNORE_MISSING))) {
186                     $courseid = $subscription->courseid;
187                     $context = $coursecontext;
188                 } else {
189                     $courseid = 0;
190                     $context = \context_system::instance();
191                 }
193                 $params = array(
194                     'objectid' => $subscription->id,
195                     'courseid' => $courseid,
196                     'context' => $context
197                 );
198                 $event = \tool_monitor\event\subscription_deleted::create($params);
199                 $event->add_record_snapshot('tool_monitor_subscriptions', $subscription);
200                 $event->trigger();
201             }
202         }
204         $subscriptions->close();
206         return $success;
207     }
209     /**
210      * Get a subscription instance for an given subscription id.
211      *
212      * @param subscription|int $subscriptionorid an instance of subscription class or id.
213      *
214      * @return subscription returns a instance of subscription class.
215      */
216     public static function get_subscription($subscriptionorid) {
217         global $DB;
219         if (is_object($subscriptionorid)) {
220             return new subscription($subscriptionorid);
221         }
223         $sql = self::get_subscription_join_rule_sql();
224         $sql .= "WHERE s.id = :id";
225         $sub = $DB->get_record_sql($sql, array('id' => $subscriptionorid), MUST_EXIST);
226         return new subscription($sub);
227     }
229     /**
230      * Get an array of subscriptions for a given user in a given course.
231      *
232      * @param int $courseid course id.
233      * @param int $limitfrom Limit from which to fetch rules.
234      * @param int $limitto  Limit to which rules need to be fetched.
235      * @param int $userid Id of the user for which the subscription needs to be fetched. Defaults to $USER;
236      * @param string $order Order to sort the subscriptions.
237      *
238      * @return array list of subscriptions
239      */
240     public static function get_user_subscriptions_for_course($courseid, $limitfrom = 0, $limitto = 0, $userid = 0,
241             $order = 's.timecreated DESC' ) {
242         global $DB, $USER;
243         if ($userid == 0) {
244             $userid = $USER->id;
245         }
246         $sql = self::get_subscription_join_rule_sql();
247         $sql .= "WHERE s.courseid = :courseid AND s.userid = :userid ORDER BY $order";
249         return self::get_instances($DB->get_records_sql($sql, array('courseid' => $courseid, 'userid' => $userid), $limitfrom,
250                 $limitto));
251     }
253     /**
254      * Get count of subscriptions for a given user in a given course.
255      *
256      * @param int $courseid course id.
257      * @param int $userid Id of the user for which the subscription needs to be fetched. Defaults to $USER;
258      *
259      * @return int number of subscriptions
260      */
261     public static function count_user_subscriptions_for_course($courseid, $userid = 0) {
262         global $DB, $USER;
263         if ($userid == 0) {
264             $userid = $USER->id;
265         }
266         $sql = self::get_subscription_join_rule_sql(true);
267         $sql .= "WHERE s.courseid = :courseid AND s.userid = :userid";
269         return $DB->count_records_sql($sql, array('courseid' => $courseid, 'userid' => $userid));
270     }
272     /**
273      * Get an array of subscriptions for a given user.
274      *
275      * @param int $limitfrom Limit from which to fetch rules.
276      * @param int $limitto  Limit to which rules need to be fetched.
277      * @param int $userid Id of the user for which the subscription needs to be fetched. Defaults to $USER;
278      * @param string $order Order to sort the subscriptions.
279      *
280      * @return array list of subscriptions
281      */
282     public static function get_user_subscriptions($limitfrom = 0, $limitto = 0, $userid = 0,
283                                                              $order = 's.timecreated DESC' ) {
284         global $DB, $USER;
285         if ($userid == 0) {
286             $userid = $USER->id;
287         }
288         $sql = self::get_subscription_join_rule_sql();
289         $sql .= "WHERE s.userid = :userid ORDER BY $order";
291         return self::get_instances($DB->get_records_sql($sql, array('userid' => $userid), $limitfrom, $limitto));
292     }
294     /**
295      * Get count of subscriptions for a given user.
296      *
297      * @param int $userid Id of the user for which the subscription needs to be fetched. Defaults to $USER;
298      *
299      * @return int number of subscriptions
300      */
301     public static function count_user_subscriptions($userid = 0) {
302         global $DB, $USER;;
303         if ($userid == 0) {
304             $userid = $USER->id;
305         }
306         $sql = self::get_subscription_join_rule_sql(true);
307         $sql .= "WHERE s.userid = :userid";
309         return $DB->count_records_sql($sql, array('userid' => $userid));
310     }
312     /**
313      * Return a list of subscriptions for a given event.
314      *
315      * @param \stdClass $event the event object.
316      *
317      * @return array
318      */
319     public static function get_subscriptions_by_event(\stdClass $event) {
320         global $DB;
322         $sql = self::get_subscription_join_rule_sql();
323         if ($event->contextlevel == CONTEXT_MODULE && $event->contextinstanceid != 0) {
324             $sql .= "WHERE r.eventname = :eventname AND s.courseid = :courseid AND (s.cmid = :cmid OR s.cmid = 0)";
325             $params = array('eventname' => $event->eventname, 'courseid' => $event->courseid, 'cmid' => $event->contextinstanceid);
326         } else {
327             $sql .= "WHERE r.eventname = :eventname AND (s.courseid = :courseid OR s.courseid = 0)";
328             $params = array('eventname' => $event->eventname, 'courseid' => $event->courseid);
329         }
330         return self::get_instances($DB->get_records_sql($sql, $params));
331     }
333     /**
334      * Return sql to join rule and subscription table.
335      *
336      * @param bool $count Weather if this is a count query or not.
337      *
338      * @return string the sql.
339      */
340     protected static function get_subscription_join_rule_sql($count = false) {
341         if ($count) {
342             $select = "SELECT COUNT(s.id) ";
343         } else {
344             $select = "SELECT s.*, r.description, r.descriptionformat, r.name, r.userid as ruleuserid, r.courseid as rulecourseid,
345             r.plugin, r.eventname, r.template, r.templateformat, r.frequency, r.timewindow";
346         }
347         $sql = $select . "
348                   FROM {tool_monitor_rules} r
349                   JOIN {tool_monitor_subscriptions} s
350                         ON r.id = s.ruleid ";
351         return $sql;
352     }
354     /**
355      * Helper method to convert db records to instances.
356      *
357      * @param array $arr of subscriptions.
358      *
359      * @return array of subscriptions as instances.
360      */
361     protected static function get_instances($arr) {
362         $result = array();
363         foreach ($arr as $key => $sub) {
364             $result[$key] = new subscription($sub);
365         }
366         return $result;
367     }