Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402] [Versions 402 and 403]
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 * Forum subscription manager. 19 * 20 * @package mod_forum 21 * @copyright 2014 Andrew Nicols <andrew@nicols.co.uk> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace mod_forum; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 /** 30 * Forum subscription manager. 31 * 32 * @copyright 2014 Andrew Nicols <andrew@nicols.co.uk> 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 class subscriptions { 36 37 /** 38 * The status value for an unsubscribed discussion. 39 * 40 * @var int 41 */ 42 const FORUM_DISCUSSION_UNSUBSCRIBED = -1; 43 44 /** 45 * The subscription cache for forums. 46 * 47 * The first level key is the user ID 48 * The second level is the forum ID 49 * The Value then is bool for subscribed of not. 50 * 51 * @var array[] An array of arrays. 52 */ 53 protected static $forumcache = array(); 54 55 /** 56 * The list of forums which have been wholly retrieved for the forum subscription cache. 57 * 58 * This allows for prior caching of an entire forum to reduce the 59 * number of DB queries in a subscription check loop. 60 * 61 * @var bool[] 62 */ 63 protected static $fetchedforums = array(); 64 65 /** 66 * The subscription cache for forum discussions. 67 * 68 * The first level key is the user ID 69 * The second level is the forum ID 70 * The third level key is the discussion ID 71 * The value is then the users preference (int) 72 * 73 * @var array[] 74 */ 75 protected static $forumdiscussioncache = array(); 76 77 /** 78 * The list of forums which have been wholly retrieved for the forum discussion subscription cache. 79 * 80 * This allows for prior caching of an entire forum to reduce the 81 * number of DB queries in a subscription check loop. 82 * 83 * @var bool[] 84 */ 85 protected static $discussionfetchedforums = array(); 86 87 /** 88 * Whether a user is subscribed to this forum, or a discussion within 89 * the forum. 90 * 91 * If a discussion is specified, then report whether the user is 92 * subscribed to posts to this particular discussion, taking into 93 * account the forum preference. 94 * 95 * If it is not specified then only the forum preference is considered. 96 * 97 * @param int $userid The user ID 98 * @param \stdClass $forum The record of the forum to test 99 * @param int $discussionid The ID of the discussion to check 100 * @param $cm The coursemodule record. If not supplied, this will be calculated using get_fast_modinfo instead. 101 * @return boolean 102 */ 103 public static function is_subscribed($userid, $forum, $discussionid = null, $cm = null) { 104 // If forum is force subscribed and has allowforcesubscribe, then user is subscribed. 105 if (self::is_forcesubscribed($forum)) { 106 if (!$cm) { 107 $cm = get_fast_modinfo($forum->course)->instances['forum'][$forum->id]; 108 } 109 if (has_capability('mod/forum:allowforcesubscribe', \context_module::instance($cm->id), $userid)) { 110 return true; 111 } 112 } 113 114 if ($discussionid === null) { 115 return self::is_subscribed_to_forum($userid, $forum); 116 } 117 118 $subscriptions = self::fetch_discussion_subscription($forum->id, $userid); 119 120 // Check whether there is a record for this discussion subscription. 121 if (isset($subscriptions[$discussionid])) { 122 return ($subscriptions[$discussionid] != self::FORUM_DISCUSSION_UNSUBSCRIBED); 123 } 124 125 return self::is_subscribed_to_forum($userid, $forum); 126 } 127 128 /** 129 * Whether a user is subscribed to this forum. 130 * 131 * @param int $userid The user ID 132 * @param \stdClass $forum The record of the forum to test 133 * @return boolean 134 */ 135 protected static function is_subscribed_to_forum($userid, $forum) { 136 return self::fetch_subscription_cache($forum->id, $userid); 137 } 138 139 /** 140 * Helper to determine whether a forum has it's subscription mode set 141 * to forced subscription. 142 * 143 * @param \stdClass $forum The record of the forum to test 144 * @return bool 145 */ 146 public static function is_forcesubscribed($forum) { 147 return ($forum->forcesubscribe == FORUM_FORCESUBSCRIBE); 148 } 149 150 /** 151 * Helper to determine whether a forum has it's subscription mode set to disabled. 152 * 153 * @param \stdClass $forum The record of the forum to test 154 * @return bool 155 */ 156 public static function subscription_disabled($forum) { 157 return ($forum->forcesubscribe == FORUM_DISALLOWSUBSCRIBE); 158 } 159 160 /** 161 * Helper to determine whether the specified forum can be subscribed to. 162 * 163 * @param \stdClass $forum The record of the forum to test 164 * @return bool 165 */ 166 public static function is_subscribable($forum) { 167 return (isloggedin() && !isguestuser() && 168 !\mod_forum\subscriptions::is_forcesubscribed($forum) && 169 !\mod_forum\subscriptions::subscription_disabled($forum)); 170 } 171 172 /** 173 * Set the forum subscription mode. 174 * 175 * By default when called without options, this is set to FORUM_FORCESUBSCRIBE. 176 * 177 * @param \stdClass $forum The record of the forum to set 178 * @param int $status The new subscription state 179 * @return bool 180 */ 181 public static function set_subscription_mode($forumid, $status = 1) { 182 global $DB; 183 return $DB->set_field("forum", "forcesubscribe", $status, array("id" => $forumid)); 184 } 185 186 /** 187 * Returns the current subscription mode for the forum. 188 * 189 * @param \stdClass $forum The record of the forum to set 190 * @return int The forum subscription mode 191 */ 192 public static function get_subscription_mode($forum) { 193 return $forum->forcesubscribe; 194 } 195 196 /** 197 * Returns an array of forums that the current user is subscribed to and is allowed to unsubscribe from 198 * 199 * @return array An array of unsubscribable forums 200 */ 201 public static function get_unsubscribable_forums() { 202 global $USER, $DB; 203 204 // Get courses that $USER is enrolled in and can see. 205 $courses = enrol_get_my_courses(); 206 if (empty($courses)) { 207 return array(); 208 } 209 210 $courseids = array(); 211 foreach($courses as $course) { 212 $courseids[] = $course->id; 213 } 214 list($coursesql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'c'); 215 216 // Get all forums from the user's courses that they are subscribed to and which are not set to forced. 217 // It is possible for users to be subscribed to a forum in subscription disallowed mode so they must be listed 218 // here so that that can be unsubscribed from. 219 $sql = "SELECT f.id, cm.id as cm, cm.visible, f.course 220 FROM {forum} f 221 JOIN {course_modules} cm ON cm.instance = f.id 222 JOIN {modules} m ON m.name = :modulename AND m.id = cm.module 223 LEFT JOIN {forum_subscriptions} fs ON (fs.forum = f.id AND fs.userid = :userid) 224 WHERE f.forcesubscribe <> :forcesubscribe 225 AND fs.id IS NOT NULL 226 AND cm.course 227 $coursesql"; 228 $params = array_merge($courseparams, array( 229 'modulename'=>'forum', 230 'userid' => $USER->id, 231 'forcesubscribe' => FORUM_FORCESUBSCRIBE, 232 )); 233 $forums = $DB->get_recordset_sql($sql, $params); 234 235 $unsubscribableforums = array(); 236 foreach($forums as $forum) { 237 if (empty($forum->visible)) { 238 // The forum is hidden - check if the user can view the forum. 239 $context = \context_module::instance($forum->cm); 240 if (!has_capability('moodle/course:viewhiddenactivities', $context)) { 241 // The user can't see the hidden forum to cannot unsubscribe. 242 continue; 243 } 244 } 245 246 $unsubscribableforums[] = $forum; 247 } 248 $forums->close(); 249 250 return $unsubscribableforums; 251 } 252 253 /** 254 * Get the list of potential subscribers to a forum. 255 * 256 * @param context_module $context the forum context. 257 * @param integer $groupid the id of a group, or 0 for all groups. 258 * @param string $fields the list of fields to return for each user. As for get_users_by_capability. 259 * @param string $sort sort order. As for get_users_by_capability. 260 * @return array list of users. 261 */ 262 public static function get_potential_subscribers($context, $groupid, $fields, $sort = '') { 263 global $DB; 264 265 // Only active enrolled users or everybody on the frontpage. 266 list($esql, $params) = get_enrolled_sql($context, 'mod/forum:allowforcesubscribe', $groupid, true); 267 if (!$sort) { 268 list($sort, $sortparams) = users_order_by_sql('u'); 269 $params = array_merge($params, $sortparams); 270 } 271 272 $sql = "SELECT $fields 273 FROM {user} u 274 JOIN ($esql) je ON je.id = u.id 275 WHERE u.auth <> 'nologin' AND u.suspended = 0 AND u.confirmed = 1 276 ORDER BY $sort"; 277 278 return $DB->get_records_sql($sql, $params); 279 } 280 281 /** 282 * Fetch the forum subscription data for the specified userid and forum. 283 * 284 * @param int $forumid The forum to retrieve a cache for 285 * @param int $userid The user ID 286 * @return boolean 287 */ 288 public static function fetch_subscription_cache($forumid, $userid) { 289 if (isset(self::$forumcache[$userid]) && isset(self::$forumcache[$userid][$forumid])) { 290 return self::$forumcache[$userid][$forumid]; 291 } 292 self::fill_subscription_cache($forumid, $userid); 293 294 if (!isset(self::$forumcache[$userid]) || !isset(self::$forumcache[$userid][$forumid])) { 295 return false; 296 } 297 298 return self::$forumcache[$userid][$forumid]; 299 } 300 301 /** 302 * Fill the forum subscription data for the specified userid and forum. 303 * 304 * If the userid is not specified, then all subscription data for that forum is fetched in a single query and used 305 * for subsequent lookups without requiring further database queries. 306 * 307 * @param int $forumid The forum to retrieve a cache for 308 * @param int $userid The user ID 309 * @return void 310 */ 311 public static function fill_subscription_cache($forumid, $userid = null) { 312 global $DB; 313 314 if (!isset(self::$fetchedforums[$forumid])) { 315 // This forum has not been fetched as a whole. 316 if (isset($userid)) { 317 if (!isset(self::$forumcache[$userid])) { 318 self::$forumcache[$userid] = array(); 319 } 320 321 if (!isset(self::$forumcache[$userid][$forumid])) { 322 if ($DB->record_exists('forum_subscriptions', array( 323 'userid' => $userid, 324 'forum' => $forumid, 325 ))) { 326 self::$forumcache[$userid][$forumid] = true; 327 } else { 328 self::$forumcache[$userid][$forumid] = false; 329 } 330 } 331 } else { 332 $subscriptions = $DB->get_recordset('forum_subscriptions', array( 333 'forum' => $forumid, 334 ), '', 'id, userid'); 335 foreach ($subscriptions as $id => $data) { 336 if (!isset(self::$forumcache[$data->userid])) { 337 self::$forumcache[$data->userid] = array(); 338 } 339 self::$forumcache[$data->userid][$forumid] = true; 340 } 341 self::$fetchedforums[$forumid] = true; 342 $subscriptions->close(); 343 } 344 } 345 } 346 347 /** 348 * Fill the forum subscription data for all forums that the specified userid can subscribe to in the specified course. 349 * 350 * @param int $courseid The course to retrieve a cache for 351 * @param int $userid The user ID 352 * @return void 353 */ 354 public static function fill_subscription_cache_for_course($courseid, $userid) { 355 global $DB; 356 357 if (!isset(self::$forumcache[$userid])) { 358 self::$forumcache[$userid] = array(); 359 } 360 361 $sql = "SELECT 362 f.id AS forumid, 363 s.id AS subscriptionid 364 FROM {forum} f 365 LEFT JOIN {forum_subscriptions} s ON (s.forum = f.id AND s.userid = :userid) 366 WHERE f.course = :course 367 AND f.forcesubscribe <> :subscriptionforced"; 368 369 $subscriptions = $DB->get_recordset_sql($sql, array( 370 'course' => $courseid, 371 'userid' => $userid, 372 'subscriptionforced' => FORUM_FORCESUBSCRIBE, 373 )); 374 375 foreach ($subscriptions as $id => $data) { 376 self::$forumcache[$userid][$id] = !empty($data->subscriptionid); 377 } 378 $subscriptions->close(); 379 } 380 381 /** 382 * Returns a list of user objects who are subscribed to this forum. 383 * 384 * @param stdClass $forum The forum record. 385 * @param int $groupid The group id if restricting subscriptions to a group of users, or 0 for all. 386 * @param context_module $context the forum context, to save re-fetching it where possible. 387 * @param string $fields requested user fields (with "u." table prefix). 388 * @param boolean $includediscussionsubscriptions Whether to take discussion subscriptions and unsubscriptions into consideration. 389 * @return array list of users. 390 */ 391 public static function fetch_subscribed_users($forum, $groupid = 0, $context = null, $fields = null, 392 $includediscussionsubscriptions = false) { 393 global $CFG, $DB; 394 395 if (empty($fields)) { 396 $userfieldsapi = \core_user\fields::for_name(); 397 $allnames = $userfieldsapi->get_sql('u', false, '', '', false)->selects; 398 $fields ="u.id, 399 u.username, 400 $allnames, 401 u.maildisplay, 402 u.mailformat, 403 u.maildigest, 404 u.imagealt, 405 u.email, 406 u.emailstop, 407 u.city, 408 u.country, 409 u.lastaccess, 410 u.lastlogin, 411 u.picture, 412 u.timezone, 413 u.theme, 414 u.lang, 415 u.trackforums, 416 u.mnethostid"; 417 } 418 419 // Retrieve the forum context if it wasn't specified. 420 $context = forum_get_context($forum->id, $context); 421 if (self::is_forcesubscribed($forum)) { 422 $results = self::get_potential_subscribers($context, $groupid, $fields); 423 424 } else { 425 // Only active enrolled users or everybody on the frontpage. 426 list($esql, $params) = get_enrolled_sql($context, '', $groupid, true); 427 $params['forumid'] = $forum->id; 428 429 list($sort, $sortparams) = users_order_by_sql('u'); 430 $params = array_merge($params, $sortparams); 431 432 if ($includediscussionsubscriptions) { 433 $params['sforumid'] = $forum->id; 434 $params['dsforumid'] = $forum->id; 435 $params['unsubscribed'] = self::FORUM_DISCUSSION_UNSUBSCRIBED; 436 437 $sql = "SELECT $fields 438 FROM ( 439 SELECT userid FROM {forum_subscriptions} s 440 WHERE 441 s.forum = :sforumid 442 UNION 443 SELECT userid FROM {forum_discussion_subs} ds 444 WHERE 445 ds.forum = :dsforumid AND ds.preference <> :unsubscribed 446 ) subscriptions 447 JOIN {user} u ON u.id = subscriptions.userid 448 JOIN ($esql) je ON je.id = u.id 449 WHERE u.auth <> 'nologin' AND u.suspended = 0 AND u.confirmed = 1 450 ORDER BY $sort"; 451 452 } else { 453 $sql = "SELECT $fields 454 FROM {user} u 455 JOIN ($esql) je ON je.id = u.id 456 JOIN {forum_subscriptions} s ON s.userid = u.id 457 WHERE 458 s.forum = :forumid AND u.auth <> 'nologin' AND u.suspended = 0 AND u.confirmed = 1 459 ORDER BY $sort"; 460 } 461 $results = $DB->get_records_sql($sql, $params); 462 } 463 464 // Guest user should never be subscribed to a forum. 465 unset($results[$CFG->siteguest]); 466 467 // Apply the activity module availability resetrictions. 468 $cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course); 469 $modinfo = get_fast_modinfo($forum->course); 470 $info = new \core_availability\info_module($modinfo->get_cm($cm->id)); 471 $results = $info->filter_user_list($results); 472 473 return $results; 474 } 475 476 /** 477 * Retrieve the discussion subscription data for the specified userid and forum. 478 * 479 * This is returned as an array of discussions for that forum which contain the preference in a stdClass. 480 * 481 * @param int $forumid The forum to retrieve a cache for 482 * @param int $userid The user ID 483 * @return array of stdClass objects with one per discussion in the forum. 484 */ 485 public static function fetch_discussion_subscription($forumid, $userid = null) { 486 self::fill_discussion_subscription_cache($forumid, $userid); 487 488 if (!isset(self::$forumdiscussioncache[$userid]) || !isset(self::$forumdiscussioncache[$userid][$forumid])) { 489 return array(); 490 } 491 492 return self::$forumdiscussioncache[$userid][$forumid]; 493 } 494 495 /** 496 * Fill the discussion subscription data for the specified userid and forum. 497 * 498 * If the userid is not specified, then all discussion subscription data for that forum is fetched in a single query 499 * and used for subsequent lookups without requiring further database queries. 500 * 501 * @param int $forumid The forum to retrieve a cache for 502 * @param int $userid The user ID 503 * @return void 504 */ 505 public static function fill_discussion_subscription_cache($forumid, $userid = null) { 506 global $DB; 507 508 if (!isset(self::$discussionfetchedforums[$forumid])) { 509 // This forum hasn't been fetched as a whole yet. 510 if (isset($userid)) { 511 if (!isset(self::$forumdiscussioncache[$userid])) { 512 self::$forumdiscussioncache[$userid] = array(); 513 } 514 515 if (!isset(self::$forumdiscussioncache[$userid][$forumid])) { 516 $subscriptions = $DB->get_recordset('forum_discussion_subs', array( 517 'userid' => $userid, 518 'forum' => $forumid, 519 ), null, 'id, discussion, preference'); 520 521 self::$forumdiscussioncache[$userid][$forumid] = array(); 522 foreach ($subscriptions as $id => $data) { 523 self::add_to_discussion_cache($forumid, $userid, $data->discussion, $data->preference); 524 } 525 526 $subscriptions->close(); 527 } 528 } else { 529 $subscriptions = $DB->get_recordset('forum_discussion_subs', array( 530 'forum' => $forumid, 531 ), null, 'id, userid, discussion, preference'); 532 foreach ($subscriptions as $id => $data) { 533 self::add_to_discussion_cache($forumid, $data->userid, $data->discussion, $data->preference); 534 } 535 self::$discussionfetchedforums[$forumid] = true; 536 $subscriptions->close(); 537 } 538 } 539 } 540 541 /** 542 * Add the specified discussion and user preference to the discussion 543 * subscription cache. 544 * 545 * @param int $forumid The ID of the forum that this preference belongs to 546 * @param int $userid The ID of the user that this preference belongs to 547 * @param int $discussion The ID of the discussion that this preference relates to 548 * @param int $preference The preference to store 549 */ 550 protected static function add_to_discussion_cache($forumid, $userid, $discussion, $preference) { 551 if (!isset(self::$forumdiscussioncache[$userid])) { 552 self::$forumdiscussioncache[$userid] = array(); 553 } 554 555 if (!isset(self::$forumdiscussioncache[$userid][$forumid])) { 556 self::$forumdiscussioncache[$userid][$forumid] = array(); 557 } 558 559 self::$forumdiscussioncache[$userid][$forumid][$discussion] = $preference; 560 } 561 562 /** 563 * Reset the discussion cache. 564 * 565 * This cache is used to reduce the number of database queries when 566 * checking forum discussion subscription states. 567 */ 568 public static function reset_discussion_cache() { 569 self::$forumdiscussioncache = array(); 570 self::$discussionfetchedforums = array(); 571 } 572 573 /** 574 * Reset the forum cache. 575 * 576 * This cache is used to reduce the number of database queries when 577 * checking forum subscription states. 578 */ 579 public static function reset_forum_cache() { 580 self::$forumcache = array(); 581 self::$fetchedforums = array(); 582 } 583 584 /** 585 * Adds user to the subscriber list. 586 * 587 * @param int $userid The ID of the user to subscribe 588 * @param \stdClass $forum The forum record for this forum. 589 * @param \context_module|null $context Module context, may be omitted if not known or if called for the current 590 * module set in page. 591 * @param boolean $userrequest Whether the user requested this change themselves. This has an effect on whether 592 * discussion subscriptions are removed too. 593 * @return bool|int Returns true if the user is already subscribed, or the forum_subscriptions ID if the user was 594 * successfully subscribed. 595 */ 596 public static function subscribe_user($userid, $forum, $context = null, $userrequest = false) { 597 global $DB; 598 599 if (self::is_subscribed($userid, $forum)) { 600 return true; 601 } 602 603 $sub = new \stdClass(); 604 $sub->userid = $userid; 605 $sub->forum = $forum->id; 606 607 $result = $DB->insert_record("forum_subscriptions", $sub); 608 609 if ($userrequest) { 610 $discussionsubscriptions = $DB->get_recordset('forum_discussion_subs', array('userid' => $userid, 'forum' => $forum->id)); 611 $DB->delete_records_select('forum_discussion_subs', 612 'userid = :userid AND forum = :forumid AND preference <> :preference', array( 613 'userid' => $userid, 614 'forumid' => $forum->id, 615 'preference' => self::FORUM_DISCUSSION_UNSUBSCRIBED, 616 )); 617 618 // Reset the subscription caches for this forum. 619 // We know that the there were previously entries and there aren't any more. 620 if (isset(self::$forumdiscussioncache[$userid]) && isset(self::$forumdiscussioncache[$userid][$forum->id])) { 621 foreach (self::$forumdiscussioncache[$userid][$forum->id] as $discussionid => $preference) { 622 if ($preference != self::FORUM_DISCUSSION_UNSUBSCRIBED) { 623 unset(self::$forumdiscussioncache[$userid][$forum->id][$discussionid]); 624 } 625 } 626 } 627 } 628 629 // Reset the cache for this forum. 630 self::$forumcache[$userid][$forum->id] = true; 631 632 $context = forum_get_context($forum->id, $context); 633 $params = array( 634 'context' => $context, 635 'objectid' => $result, 636 'relateduserid' => $userid, 637 'other' => array('forumid' => $forum->id), 638 639 ); 640 $event = event\subscription_created::create($params); 641 if ($userrequest && $discussionsubscriptions) { 642 foreach ($discussionsubscriptions as $subscription) { 643 $event->add_record_snapshot('forum_discussion_subs', $subscription); 644 } 645 $discussionsubscriptions->close(); 646 } 647 $event->trigger(); 648 649 return $result; 650 } 651 652 /** 653 * Removes user from the subscriber list 654 * 655 * @param int $userid The ID of the user to unsubscribe 656 * @param \stdClass $forum The forum record for this forum. 657 * @param \context_module|null $context Module context, may be omitted if not known or if called for the current 658 * module set in page. 659 * @param boolean $userrequest Whether the user requested this change themselves. This has an effect on whether 660 * discussion subscriptions are removed too. 661 * @return boolean Always returns true. 662 */ 663 public static function unsubscribe_user($userid, $forum, $context = null, $userrequest = false) { 664 global $DB; 665 666 $sqlparams = array( 667 'userid' => $userid, 668 'forum' => $forum->id, 669 ); 670 $DB->delete_records('forum_digests', $sqlparams); 671 672 if ($forumsubscription = $DB->get_record('forum_subscriptions', $sqlparams)) { 673 $DB->delete_records('forum_subscriptions', array('id' => $forumsubscription->id)); 674 675 if ($userrequest) { 676 $discussionsubscriptions = $DB->get_recordset('forum_discussion_subs', $sqlparams); 677 $DB->delete_records('forum_discussion_subs', 678 array('userid' => $userid, 'forum' => $forum->id, 'preference' => self::FORUM_DISCUSSION_UNSUBSCRIBED)); 679 680 // We know that the there were previously entries and there aren't any more. 681 if (isset(self::$forumdiscussioncache[$userid]) && isset(self::$forumdiscussioncache[$userid][$forum->id])) { 682 self::$forumdiscussioncache[$userid][$forum->id] = array(); 683 } 684 } 685 686 // Reset the cache for this forum. 687 self::$forumcache[$userid][$forum->id] = false; 688 689 $context = forum_get_context($forum->id, $context); 690 $params = array( 691 'context' => $context, 692 'objectid' => $forumsubscription->id, 693 'relateduserid' => $userid, 694 'other' => array('forumid' => $forum->id), 695 696 ); 697 $event = event\subscription_deleted::create($params); 698 $event->add_record_snapshot('forum_subscriptions', $forumsubscription); 699 if ($userrequest && $discussionsubscriptions) { 700 foreach ($discussionsubscriptions as $subscription) { 701 $event->add_record_snapshot('forum_discussion_subs', $subscription); 702 } 703 $discussionsubscriptions->close(); 704 } 705 $event->trigger(); 706 } 707 708 return true; 709 } 710 711 /** 712 * Subscribes the user to the specified discussion. 713 * 714 * @param int $userid The userid of the user being subscribed 715 * @param \stdClass $discussion The discussion to subscribe to 716 * @param \context_module|null $context Module context, may be omitted if not known or if called for the current 717 * module set in page. 718 * @return boolean Whether a change was made 719 */ 720 public static function subscribe_user_to_discussion($userid, $discussion, $context = null) { 721 global $DB; 722 723 // First check whether the user is subscribed to the discussion already. 724 $subscription = $DB->get_record('forum_discussion_subs', array('userid' => $userid, 'discussion' => $discussion->id)); 725 if ($subscription) { 726 if ($subscription->preference != self::FORUM_DISCUSSION_UNSUBSCRIBED) { 727 // The user is already subscribed to the discussion. Ignore. 728 return false; 729 } 730 } 731 // No discussion-level subscription. Check for a forum level subscription. 732 if ($DB->record_exists('forum_subscriptions', array('userid' => $userid, 'forum' => $discussion->forum))) { 733 if ($subscription && $subscription->preference == self::FORUM_DISCUSSION_UNSUBSCRIBED) { 734 // The user is subscribed to the forum, but unsubscribed from the discussion, delete the discussion preference. 735 $DB->delete_records('forum_discussion_subs', array('id' => $subscription->id)); 736 unset(self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id]); 737 } else { 738 // The user is already subscribed to the forum. Ignore. 739 return false; 740 } 741 } else { 742 if ($subscription) { 743 $subscription->preference = time(); 744 $DB->update_record('forum_discussion_subs', $subscription); 745 } else { 746 $subscription = new \stdClass(); 747 $subscription->userid = $userid; 748 $subscription->forum = $discussion->forum; 749 $subscription->discussion = $discussion->id; 750 $subscription->preference = time(); 751 752 $subscription->id = $DB->insert_record('forum_discussion_subs', $subscription); 753 self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id] = $subscription->preference; 754 } 755 } 756 757 $context = forum_get_context($discussion->forum, $context); 758 $params = array( 759 'context' => $context, 760 'objectid' => $subscription->id, 761 'relateduserid' => $userid, 762 'other' => array( 763 'forumid' => $discussion->forum, 764 'discussion' => $discussion->id, 765 ), 766 767 ); 768 $event = event\discussion_subscription_created::create($params); 769 $event->trigger(); 770 771 return true; 772 } 773 /** 774 * Unsubscribes the user from the specified discussion. 775 * 776 * @param int $userid The userid of the user being unsubscribed 777 * @param \stdClass $discussion The discussion to unsubscribe from 778 * @param \context_module|null $context Module context, may be omitted if not known or if called for the current 779 * module set in page. 780 * @return boolean Whether a change was made 781 */ 782 public static function unsubscribe_user_from_discussion($userid, $discussion, $context = null) { 783 global $DB; 784 785 // First check whether the user's subscription preference for this discussion. 786 $subscription = $DB->get_record('forum_discussion_subs', array('userid' => $userid, 'discussion' => $discussion->id)); 787 if ($subscription) { 788 if ($subscription->preference == self::FORUM_DISCUSSION_UNSUBSCRIBED) { 789 // The user is already unsubscribed from the discussion. Ignore. 790 return false; 791 } 792 } 793 // No discussion-level preference. Check for a forum level subscription. 794 if (!$DB->record_exists('forum_subscriptions', array('userid' => $userid, 'forum' => $discussion->forum))) { 795 if ($subscription && $subscription->preference != self::FORUM_DISCUSSION_UNSUBSCRIBED) { 796 // The user is not subscribed to the forum, but subscribed from the discussion, delete the discussion subscription. 797 $DB->delete_records('forum_discussion_subs', array('id' => $subscription->id)); 798 unset(self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id]); 799 } else { 800 // The user is not subscribed from the forum. Ignore. 801 return false; 802 } 803 } else { 804 if ($subscription) { 805 $subscription->preference = self::FORUM_DISCUSSION_UNSUBSCRIBED; 806 $DB->update_record('forum_discussion_subs', $subscription); 807 } else { 808 $subscription = new \stdClass(); 809 $subscription->userid = $userid; 810 $subscription->forum = $discussion->forum; 811 $subscription->discussion = $discussion->id; 812 $subscription->preference = self::FORUM_DISCUSSION_UNSUBSCRIBED; 813 814 $subscription->id = $DB->insert_record('forum_discussion_subs', $subscription); 815 } 816 self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id] = $subscription->preference; 817 } 818 819 $context = forum_get_context($discussion->forum, $context); 820 $params = array( 821 'context' => $context, 822 'objectid' => $subscription->id, 823 'relateduserid' => $userid, 824 'other' => array( 825 'forumid' => $discussion->forum, 826 'discussion' => $discussion->id, 827 ), 828 829 ); 830 $event = event\discussion_subscription_deleted::create($params); 831 $event->trigger(); 832 833 return true; 834 } 835 836 /** 837 * Gets the default subscription value for the logged in user. 838 * 839 * @param \stdClass $forum The forum record 840 * @param \context $context The course context 841 * @param \cm_info $cm cm_info 842 * @param int|null $discussionid The discussion we are checking against 843 * @return bool Default subscription 844 * @throws coding_exception 845 */ 846 public static function get_user_default_subscription($forum, $context, $cm, ?int $discussionid) { 847 global $USER; 848 $manageactivities = has_capability('moodle/course:manageactivities', $context); 849 if (\mod_forum\subscriptions::subscription_disabled($forum) && !$manageactivities) { 850 // User does not have permission to subscribe to this discussion at all. 851 $discussionsubscribe = false; 852 } else if (\mod_forum\subscriptions::is_forcesubscribed($forum)) { 853 // User does not have permission to unsubscribe from this discussion at all. 854 $discussionsubscribe = true; 855 } else { 856 if (isset($discussionid) && self::is_subscribed($USER->id, $forum, $discussionid, $cm)) { 857 // User is subscribed to the discussion - continue the subscription. 858 $discussionsubscribe = true; 859 } else if (!isset($discussionid) && \mod_forum\subscriptions::is_subscribed($USER->id, $forum, null, $cm)) { 860 // Starting a new discussion, and the user is subscribed to the forum - subscribe to the discussion. 861 $discussionsubscribe = true; 862 } else { 863 // User is not subscribed to either forum or discussion. Follow user preference. 864 $discussionsubscribe = $USER->autosubscribe ?? false; 865 } 866 } 867 868 return $discussionsubscribe; 869 } 870 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body