MDL-47892 tool_monitor: add count_rule_subscriptions method and unit tests
[moodle.git] / admin / tool / monitor / classes / subscription_manager.php
CommitLineData
c8a081cc
AA
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/>.
16
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 */
24
25namespace tool_monitor;
26
27defined('MOODLE_INTERNAL') || die();
28
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 */
37class 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;
50
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 }
60
61 $subscription->timecreated = time();
229f8419
MN
62 $subscription->id = $DB->insert_record('tool_monitor_subscriptions', $subscription);
63
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 }
73
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 }
82
83 return $subscription->id;
c8a081cc
AA
84 }
85
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;
ac0e4dad 97 if (is_object($subscriptionorid)) {
c8a081cc
AA
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 }
1adb0031
MN
105
106 // Store the subscription before we delete it.
107 $subscription = $DB->get_record('tool_monitor_subscriptions', array('id' => $subscription->id));
108
109 $success = $DB->delete_records('tool_monitor_subscriptions', array('id' => $subscription->id));
110
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 }
120
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 }
130
131 return $success;
c8a081cc
AA
132 }
133
e24e0d24
AA
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 }
145
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 }
157
c8a081cc
AA
158 /**
159 * Delete all subscribers for a given rule.
160 *
161 * @param int $ruleid rule id.
1adb0031
MN
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.
c8a081cc
AA
164 *
165 * @return bool
166 */
1adb0031 167 public static function remove_all_subscriptions_for_rule($ruleid, $coursecontext = null) {
c8a081cc 168 global $DB;
1adb0031
MN
169
170 // Store all the subscriptions we have to delete.
171 $subscriptions = $DB->get_recordset('tool_monitor_subscriptions', array('ruleid' => $ruleid));
172
173 // Now delete them.
174 $success = $DB->delete_records('tool_monitor_subscriptions', array('ruleid' => $ruleid));
175
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 }
192
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 }
203
d9e879e5
FM
204 $subscriptions->close();
205
1adb0031 206 return $success;
c8a081cc
AA
207 }
208
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;
218
219 if (is_object($subscriptionorid)) {
220 return new subscription($subscriptionorid);
221 }
222
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 }
228
229 /**
230 * Get an array of subscriptions for a given user in a given course.
231 *
232 * @param int $courseid course id.
ac0e4dad
AA
233 * @param int $limitfrom Limit from which to fetch rules.
234 * @param int $limitto Limit to which rules need to be fetched.
c8a081cc
AA
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 */
ac0e4dad
AA
240 public static function get_user_subscriptions_for_course($courseid, $limitfrom = 0, $limitto = 0, $userid = 0,
241 $order = 's.timecreated DESC' ) {
c8a081cc
AA
242 global $DB, $USER;
243 if ($userid == 0) {
244 $userid = $USER->id;
245 }
246 $sql = self::get_subscription_join_rule_sql();
ac0e4dad 247 $sql .= "WHERE s.courseid = :courseid AND s.userid = :userid ORDER BY $order";
c8a081cc 248
01d070e7
AA
249 return self::get_instances($DB->get_records_sql($sql, array('courseid' => $courseid, 'userid' => $userid), $limitfrom,
250 $limitto));
c8a081cc
AA
251 }
252
ac0e4dad
AA
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 *
ffe9ed54 259 * @return int number of subscriptions
ac0e4dad
AA
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";
268
269 return $DB->count_records_sql($sql, array('courseid' => $courseid, 'userid' => $userid));
270 }
271
ffe9ed54
AA
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";
290
291 return self::get_instances($DB->get_records_sql($sql, array('userid' => $userid), $limitfrom, $limitto));
292 }
293
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";
308
309 return $DB->count_records_sql($sql, array('userid' => $userid));
310 }
311
c8a081cc
AA
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;
321
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 }
01d070e7 330 return self::get_instances($DB->get_records_sql($sql, $params));
c8a081cc
AA
331 }
332
333 /**
334 * Return sql to join rule and subscription table.
335 *
ac0e4dad
AA
336 * @param bool $count Weather if this is a count query or not.
337 *
c8a081cc
AA
338 * @return string the sql.
339 */
01d070e7 340 protected static function get_subscription_join_rule_sql($count = false) {
ac0e4dad
AA
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 . "
c8a081cc
AA
348 FROM {tool_monitor_rules} r
349 JOIN {tool_monitor_subscriptions} s
350 ON r.id = s.ruleid ";
351 return $sql;
352 }
01d070e7
AA
353
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 }
ed9084f7
SL
368
369 /**
370 * Get count of subscriptions for a given rule.
371 *
372 * @param int $ruleid rule id of the subscription.
373 *
374 * @return int number of subscriptions
375 */
376 public static function count_rule_subscriptions($ruleid) {
377 global $DB;
378 $sql = self::get_subscription_join_rule_sql(true);
379 $sql .= "WHERE s.ruleid = :ruleid";
380
381 return $DB->count_records_sql($sql, array('ruleid' => $ruleid));
382 }
c8a081cc 383}