Search moodle.org's
Developer Documentation

   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 (!\mod_forum\subscriptions::is_forcesubscribed($forum) &&
 168                  !\mod_forum\subscriptions::subscription_disabled($forum));
 169      }
 170  
 171      /**
 172       * Set the forum subscription mode.
 173       *
 174       * By default when called without options, this is set to FORUM_FORCESUBSCRIBE.
 175       *
 176       * @param \stdClass $forum The record of the forum to set
 177       * @param int $status The new subscription state
 178       * @return bool
 179       */
 180      public static function set_subscription_mode($forumid, $status = 1) {
 181          global $DB;
 182          return $DB->set_field("forum", "forcesubscribe", $status, array("id" => $forumid));
 183      }
 184  
 185      /**
 186       * Returns the current subscription mode for the forum.
 187       *
 188       * @param \stdClass $forum The record of the forum to set
 189       * @return int The forum subscription mode
 190       */
 191      public static function get_subscription_mode($forum) {
 192          return $forum->forcesubscribe;
 193      }
 194  
 195      /**
 196       * Returns an array of forums that the current user is subscribed to and is allowed to unsubscribe from
 197       *
 198       * @return array An array of unsubscribable forums
 199       */
 200      public static function get_unsubscribable_forums() {
 201          global $USER, $DB;
 202  
 203          // Get courses that $USER is enrolled in and can see.
 204          $courses = enrol_get_my_courses();
 205          if (empty($courses)) {
 206              return array();
 207          }
 208  
 209          $courseids = array();
 210          foreach($courses as $course) {
 211              $courseids[] = $course->id;
 212          }
 213          list($coursesql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'c');
 214  
 215          // Get all forums from the user's courses that they are subscribed to and which are not set to forced.
 216          // It is possible for users to be subscribed to a forum in subscription disallowed mode so they must be listed
 217          // here so that that can be unsubscribed from.
 218          $sql = "SELECT f.id, cm.id as cm, cm.visible, f.course
 219                  FROM {forum} f
 220                  JOIN {course_modules} cm ON cm.instance = f.id
 221                  JOIN {modules} m ON m.name = :modulename AND m.id = cm.module
 222                  LEFT JOIN {forum_subscriptions} fs ON (fs.forum = f.id AND fs.userid = :userid)
 223                  WHERE f.forcesubscribe <> :forcesubscribe
 224                  AND fs.id IS NOT NULL
 225                  AND cm.course
 226                  $coursesql";
 227          $params = array_merge($courseparams, array(
 228              'modulename'=>'forum',
 229              'userid' => $USER->id,
 230              'forcesubscribe' => FORUM_FORCESUBSCRIBE,
 231          ));
 232          $forums = $DB->get_recordset_sql($sql, $params);
 233  
 234          $unsubscribableforums = array();
 235          foreach($forums as $forum) {
 236              if (empty($forum->visible)) {
 237                  // The forum is hidden - check if the user can view the forum.
 238                  $context = \context_module::instance($forum->cm);
 239                  if (!has_capability('moodle/course:viewhiddenactivities', $context)) {
 240                      // The user can't see the hidden forum to cannot unsubscribe.
 241                      continue;
 242                  }
 243              }
 244  
 245              $unsubscribableforums[] = $forum;
 246          }
 247          $forums->close();
 248  
 249          return $unsubscribableforums;
 250      }
 251  
 252      /**
 253       * Get the list of potential subscribers to a forum.
 254       *
 255       * @param context_module $context the forum context.
 256       * @param integer $groupid the id of a group, or 0 for all groups.
 257       * @param string $fields the list of fields to return for each user. As for get_users_by_capability.
 258       * @param string $sort sort order. As for get_users_by_capability.
 259       * @return array list of users.
 260       */
 261      public static function get_potential_subscribers($context, $groupid, $fields, $sort = '') {
 262          global $DB;
 263  
 264          // Only active enrolled users or everybody on the frontpage.
 265          list($esql, $params) = get_enrolled_sql($context, 'mod/forum:allowforcesubscribe', $groupid, true);
 266          if (!$sort) {
 267              list($sort, $sortparams) = users_order_by_sql('u');
 268              $params = array_merge($params, $sortparams);
 269          }
 270  
 271          $sql = "SELECT $fields
 272                  FROM {user} u
 273                  JOIN ($esql) je ON je.id = u.id
 274              ORDER BY $sort";
 275  
 276          return $DB->get_records_sql($sql, $params);
 277      }
 278  
 279      /**
 280       * Fetch the forum subscription data for the specified userid and forum.
 281       *
 282       * @param int $forumid The forum to retrieve a cache for
 283       * @param int $userid The user ID
 284       * @return boolean
 285       */
 286      public static function fetch_subscription_cache($forumid, $userid) {
 287          if (isset(self::$forumcache[$userid]) && isset(self::$forumcache[$userid][$forumid])) {
 288              return self::$forumcache[$userid][$forumid];
 289          }
 290          self::fill_subscription_cache($forumid, $userid);
 291  
 292          if (!isset(self::$forumcache[$userid]) || !isset(self::$forumcache[$userid][$forumid])) {
 293              return false;
 294          }
 295  
 296          return self::$forumcache[$userid][$forumid];
 297      }
 298  
 299      /**
 300       * Fill the forum subscription data for the specified userid and forum.
 301       *
 302       * If the userid is not specified, then all subscription data for that forum is fetched in a single query and used
 303       * for subsequent lookups without requiring further database queries.
 304       *
 305       * @param int $forumid The forum to retrieve a cache for
 306       * @param int $userid The user ID
 307       * @return void
 308       */
 309      public static function fill_subscription_cache($forumid, $userid = null) {
 310          global $DB;
 311  
 312          if (!isset(self::$fetchedforums[$forumid])) {
 313              // This forum has not been fetched as a whole.
 314              if (isset($userid)) {
 315                  if (!isset(self::$forumcache[$userid])) {
 316                      self::$forumcache[$userid] = array();
 317                  }
 318  
 319                  if (!isset(self::$forumcache[$userid][$forumid])) {
 320                      if ($DB->record_exists('forum_subscriptions', array(
 321                          'userid' => $userid,
 322                          'forum' => $forumid,
 323                      ))) {
 324                          self::$forumcache[$userid][$forumid] = true;
 325                      } else {
 326                          self::$forumcache[$userid][$forumid] = false;
 327                      }
 328                  }
 329              } else {
 330                  $subscriptions = $DB->get_recordset('forum_subscriptions', array(
 331                      'forum' => $forumid,
 332                  ), '', 'id, userid');
 333                  foreach ($subscriptions as $id => $data) {
 334                      if (!isset(self::$forumcache[$data->userid])) {
 335                          self::$forumcache[$data->userid] = array();
 336                      }
 337                      self::$forumcache[$data->userid][$forumid] = true;
 338                  }
 339                  self::$fetchedforums[$forumid] = true;
 340                  $subscriptions->close();
 341              }
 342          }
 343      }
 344  
 345      /**
 346       * Fill the forum subscription data for all forums that the specified userid can subscribe to in the specified course.
 347       *
 348       * @param int $courseid The course to retrieve a cache for
 349       * @param int $userid The user ID
 350       * @return void
 351       */
 352      public static function fill_subscription_cache_for_course($courseid, $userid) {
 353          global $DB;
 354  
 355          if (!isset(self::$forumcache[$userid])) {
 356              self::$forumcache[$userid] = array();
 357          }
 358  
 359          $sql = "SELECT
 360                      f.id AS forumid,
 361                      s.id AS subscriptionid
 362                  FROM {forum} f
 363                  LEFT JOIN {forum_subscriptions} s ON (s.forum = f.id AND s.userid = :userid)
 364                  WHERE f.course = :course
 365                  AND f.forcesubscribe <> :subscriptionforced";
 366  
 367          $subscriptions = $DB->get_recordset_sql($sql, array(
 368              'course' => $courseid,
 369              'userid' => $userid,
 370              'subscriptionforced' => FORUM_FORCESUBSCRIBE,
 371          ));
 372  
 373          foreach ($subscriptions as $id => $data) {
 374              self::$forumcache[$userid][$id] = !empty($data->subscriptionid);
 375          }
 376          $subscriptions->close();
 377      }
 378  
 379      /**
 380       * Returns a list of user objects who are subscribed to this forum.
 381       *
 382       * @param stdClass $forum The forum record.
 383       * @param int $groupid The group id if restricting subscriptions to a group of users, or 0 for all.
 384       * @param context_module $context the forum context, to save re-fetching it where possible.
 385       * @param string $fields requested user fields (with "u." table prefix).
 386       * @param boolean $includediscussionsubscriptions Whether to take discussion subscriptions and unsubscriptions into consideration.
 387       * @return array list of users.
 388       */
 389      public static function fetch_subscribed_users($forum, $groupid = 0, $context = null, $fields = null,
 390              $includediscussionsubscriptions = false) {
 391          global $CFG, $DB;
 392  
 393          if (empty($fields)) {
 394              $allnames = get_all_user_name_fields(true, 'u');
 395              $fields ="u.id,
 396                        u.username,
 397                        $allnames,
 398                        u.maildisplay,
 399                        u.mailformat,
 400                        u.maildigest,
 401                        u.imagealt,
 402                        u.email,
 403                        u.emailstop,
 404                        u.city,
 405                        u.country,
 406                        u.lastaccess,
 407                        u.lastlogin,
 408                        u.picture,
 409                        u.timezone,
 410                        u.theme,
 411                        u.lang,
 412                        u.trackforums,
 413                        u.mnethostid";
 414          }
 415  
 416          // Retrieve the forum context if it wasn't specified.
 417          $context = forum_get_context($forum->id, $context);
 418  
 419          if (self::is_forcesubscribed($forum)) {
 420              $results = \mod_forum\subscriptions::get_potential_subscribers($context, $groupid, $fields, "u.email ASC");
 421  
 422          } else {
 423              // Only active enrolled users or everybody on the frontpage.
 424              list($esql, $params) = get_enrolled_sql($context, '', $groupid, true);
 425              $params['forumid'] = $forum->id;
 426  
 427              if ($includediscussionsubscriptions) {
 428                  $params['sforumid'] = $forum->id;
 429                  $params['dsforumid'] = $forum->id;
 430                  $params['unsubscribed'] = self::FORUM_DISCUSSION_UNSUBSCRIBED;
 431  
 432                  $sql = "SELECT $fields
 433                          FROM (
 434                              SELECT userid FROM {forum_subscriptions} s
 435                              WHERE
 436                                  s.forum = :sforumid
 437                                  UNION
 438                              SELECT userid FROM {forum_discussion_subs} ds
 439                              WHERE
 440                                  ds.forum = :dsforumid AND ds.preference <> :unsubscribed
 441                          ) subscriptions
 442                          JOIN {user} u ON u.id = subscriptions.userid
 443                          JOIN ($esql) je ON je.id = u.id
 444                          ORDER BY u.email ASC";
 445  
 446              } else {
 447                  $sql = "SELECT $fields
 448                          FROM {user} u
 449                          JOIN ($esql) je ON je.id = u.id
 450                          JOIN {forum_subscriptions} s ON s.userid = u.id
 451                          WHERE
 452                            s.forum = :forumid
 453                          ORDER BY u.email ASC";
 454              }
 455              $results = $DB->get_records_sql($sql, $params);
 456          }
 457  
 458          // Guest user should never be subscribed to a forum.
 459          unset($results[$CFG->siteguest]);
 460  
 461          // Apply the activity module availability resetrictions.
 462          $cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course);
 463          $modinfo = get_fast_modinfo($forum->course);
 464          $info = new \core_availability\info_module($modinfo->get_cm($cm->id));
 465          $results = $info->filter_user_list($results);
 466  
 467          return $results;
 468      }
 469  
 470      /**
 471       * Retrieve the discussion subscription data for the specified userid and forum.
 472       *
 473       * This is returned as an array of discussions for that forum which contain the preference in a stdClass.
 474       *
 475       * @param int $forumid The forum to retrieve a cache for
 476       * @param int $userid The user ID
 477       * @return array of stdClass objects with one per discussion in the forum.
 478       */
 479      public static function fetch_discussion_subscription($forumid, $userid = null) {
 480          self::fill_discussion_subscription_cache($forumid, $userid);
 481  
 482          if (!isset(self::$forumdiscussioncache[$userid]) || !isset(self::$forumdiscussioncache[$userid][$forumid])) {
 483              return array();
 484          }
 485  
 486          return self::$forumdiscussioncache[$userid][$forumid];
 487      }
 488  
 489      /**
 490       * Fill the discussion subscription data for the specified userid and forum.
 491       *
 492       * If the userid is not specified, then all discussion subscription data for that forum is fetched in a single query
 493       * and used for subsequent lookups without requiring further database queries.
 494       *
 495       * @param int $forumid The forum to retrieve a cache for
 496       * @param int $userid The user ID
 497       * @return void
 498       */
 499      public static function fill_discussion_subscription_cache($forumid, $userid = null) {
 500          global $DB;
 501  
 502          if (!isset(self::$discussionfetchedforums[$forumid])) {
 503              // This forum hasn't been fetched as a whole yet.
 504              if (isset($userid)) {
 505                  if (!isset(self::$forumdiscussioncache[$userid])) {
 506                      self::$forumdiscussioncache[$userid] = array();
 507                  }
 508  
 509                  if (!isset(self::$forumdiscussioncache[$userid][$forumid])) {
 510                      $subscriptions = $DB->get_recordset('forum_discussion_subs', array(
 511                          'userid' => $userid,
 512                          'forum' => $forumid,
 513                      ), null, 'id, discussion, preference');
 514                      foreach ($subscriptions as $id => $data) {
 515                          self::add_to_discussion_cache($forumid, $userid, $data->discussion, $data->preference);
 516                      }
 517                      $subscriptions->close();
 518                  }
 519              } else {
 520                  $subscriptions = $DB->get_recordset('forum_discussion_subs', array(
 521                      'forum' => $forumid,
 522                  ), null, 'id, userid, discussion, preference');
 523                  foreach ($subscriptions as $id => $data) {
 524                      self::add_to_discussion_cache($forumid, $data->userid, $data->discussion, $data->preference);
 525                  }
 526                  self::$discussionfetchedforums[$forumid] = true;
 527                  $subscriptions->close();
 528              }
 529          }
 530      }
 531  
 532      /**
 533       * Add the specified discussion and user preference to the discussion
 534       * subscription cache.
 535       *
 536       * @param int $forumid The ID of the forum that this preference belongs to
 537       * @param int $userid The ID of the user that this preference belongs to
 538       * @param int $discussion The ID of the discussion that this preference relates to
 539       * @param int $preference The preference to store
 540       */
 541      protected static function add_to_discussion_cache($forumid, $userid, $discussion, $preference) {
 542          if (!isset(self::$forumdiscussioncache[$userid])) {
 543              self::$forumdiscussioncache[$userid] = array();
 544          }
 545  
 546          if (!isset(self::$forumdiscussioncache[$userid][$forumid])) {
 547              self::$forumdiscussioncache[$userid][$forumid] = array();
 548          }
 549  
 550          self::$forumdiscussioncache[$userid][$forumid][$discussion] = $preference;
 551      }
 552  
 553      /**
 554       * Reset the discussion cache.
 555       *
 556       * This cache is used to reduce the number of database queries when
 557       * checking forum discussion subscription states.
 558       */
 559      public static function reset_discussion_cache() {
 560          self::$forumdiscussioncache = array();
 561          self::$discussionfetchedforums = array();
 562      }
 563  
 564      /**
 565       * Reset the forum cache.
 566       *
 567       * This cache is used to reduce the number of database queries when
 568       * checking forum subscription states.
 569       */
 570      public static function reset_forum_cache() {
 571          self::$forumcache = array();
 572          self::$fetchedforums = array();
 573      }
 574  
 575      /**
 576       * Adds user to the subscriber list.
 577       *
 578       * @param int $userid The ID of the user to subscribe
 579       * @param \stdClass $forum The forum record for this forum.
 580       * @param \context_module|null $context Module context, may be omitted if not known or if called for the current
 581       *      module set in page.
 582       * @param boolean $userrequest Whether the user requested this change themselves. This has an effect on whether
 583       *     discussion subscriptions are removed too.
 584       * @return bool|int Returns true if the user is already subscribed, or the forum_subscriptions ID if the user was
 585       *     successfully subscribed.
 586       */
 587      public static function subscribe_user($userid, $forum, $context = null, $userrequest = false) {
 588          global $DB;
 589  
 590          if (self::is_subscribed($userid, $forum)) {
 591              return true;
 592          }
 593  
 594          $sub = new \stdClass();
 595          $sub->userid  = $userid;
 596          $sub->forum = $forum->id;
 597  
 598          $result = $DB->insert_record("forum_subscriptions", $sub);
 599  
 600          if ($userrequest) {
 601              $discussionsubscriptions = $DB->get_recordset('forum_discussion_subs', array('userid' => $userid, 'forum' => $forum->id));
 602              $DB->delete_records_select('forum_discussion_subs',
 603                      'userid = :userid AND forum = :forumid AND preference <> :preference', array(
 604                          'userid' => $userid,
 605                          'forumid' => $forum->id,
 606                          'preference' => self::FORUM_DISCUSSION_UNSUBSCRIBED,
 607                      ));
 608  
 609              // Reset the subscription caches for this forum.
 610              // We know that the there were previously entries and there aren't any more.
 611              if (isset(self::$forumdiscussioncache[$userid]) && isset(self::$forumdiscussioncache[$userid][$forum->id])) {
 612                  foreach (self::$forumdiscussioncache[$userid][$forum->id] as $discussionid => $preference) {
 613                      if ($preference != self::FORUM_DISCUSSION_UNSUBSCRIBED) {
 614                          unset(self::$forumdiscussioncache[$userid][$forum->id][$discussionid]);
 615                      }
 616                  }
 617              }
 618          }
 619  
 620          // Reset the cache for this forum.
 621          self::$forumcache[$userid][$forum->id] = true;
 622  
 623          $context = forum_get_context($forum->id, $context);
 624          $params = array(
 625              'context' => $context,
 626              'objectid' => $result,
 627              'relateduserid' => $userid,
 628              'other' => array('forumid' => $forum->id),
 629  
 630          );
 631          $event  = event\subscription_created::create($params);
 632          if ($userrequest && $discussionsubscriptions) {
 633              foreach ($discussionsubscriptions as $subscription) {
 634                  $event->add_record_snapshot('forum_discussion_subs', $subscription);
 635              }
 636              $discussionsubscriptions->close();
 637          }
 638          $event->trigger();
 639  
 640          return $result;
 641      }
 642  
 643      /**
 644       * Removes user from the subscriber list
 645       *
 646       * @param int $userid The ID of the user to unsubscribe
 647       * @param \stdClass $forum The forum record for this forum.
 648       * @param \context_module|null $context Module context, may be omitted if not known or if called for the current
 649       *     module set in page.
 650       * @param boolean $userrequest Whether the user requested this change themselves. This has an effect on whether
 651       *     discussion subscriptions are removed too.
 652       * @return boolean Always returns true.
 653       */
 654      public static function unsubscribe_user($userid, $forum, $context = null, $userrequest = false) {
 655          global $DB;
 656  
 657          $sqlparams = array(
 658              'userid' => $userid,
 659              'forum' => $forum->id,
 660          );
 661          $DB->delete_records('forum_digests', $sqlparams);
 662  
 663          if ($forumsubscription = $DB->get_record('forum_subscriptions', $sqlparams)) {
 664              $DB->delete_records('forum_subscriptions', array('id' => $forumsubscription->id));
 665  
 666              if ($userrequest) {
 667                  $discussionsubscriptions = $DB->get_recordset('forum_discussion_subs', $sqlparams);
 668                  $DB->delete_records('forum_discussion_subs',
 669                          array('userid' => $userid, 'forum' => $forum->id, 'preference' => self::FORUM_DISCUSSION_UNSUBSCRIBED));
 670  
 671                  // We know that the there were previously entries and there aren't any more.
 672                  if (isset(self::$forumdiscussioncache[$userid]) && isset(self::$forumdiscussioncache[$userid][$forum->id])) {
 673                      self::$forumdiscussioncache[$userid][$forum->id] = array();
 674                  }
 675              }
 676  
 677              // Reset the cache for this forum.
 678              self::$forumcache[$userid][$forum->id] = false;
 679  
 680              $context = forum_get_context($forum->id, $context);
 681              $params = array(
 682                  'context' => $context,
 683                  'objectid' => $forumsubscription->id,
 684                  'relateduserid' => $userid,
 685                  'other' => array('forumid' => $forum->id),
 686  
 687              );
 688              $event = event\subscription_deleted::create($params);
 689              $event->add_record_snapshot('forum_subscriptions', $forumsubscription);
 690              if ($userrequest && $discussionsubscriptions) {
 691                  foreach ($discussionsubscriptions as $subscription) {
 692                      $event->add_record_snapshot('forum_discussion_subs', $subscription);
 693                  }
 694                  $discussionsubscriptions->close();
 695              }
 696              $event->trigger();
 697          }
 698  
 699          return true;
 700      }
 701  
 702      /**
 703       * Subscribes the user to the specified discussion.
 704       *
 705       * @param int $userid The userid of the user being subscribed
 706       * @param \stdClass $discussion The discussion to subscribe to
 707       * @param \context_module|null $context Module context, may be omitted if not known or if called for the current
 708       *     module set in page.
 709       * @return boolean Whether a change was made
 710       */
 711      public static function subscribe_user_to_discussion($userid, $discussion, $context = null) {
 712          global $DB;
 713  
 714          // First check whether the user is subscribed to the discussion already.
 715          $subscription = $DB->get_record('forum_discussion_subs', array('userid' => $userid, 'discussion' => $discussion->id));
 716          if ($subscription) {
 717              if ($subscription->preference != self::FORUM_DISCUSSION_UNSUBSCRIBED) {
 718                  // The user is already subscribed to the discussion. Ignore.
 719                  return false;
 720              }
 721          }
 722          // No discussion-level subscription. Check for a forum level subscription.
 723          if ($DB->record_exists('forum_subscriptions', array('userid' => $userid, 'forum' => $discussion->forum))) {
 724              if ($subscription && $subscription->preference == self::FORUM_DISCUSSION_UNSUBSCRIBED) {
 725                  // The user is subscribed to the forum, but unsubscribed from the discussion, delete the discussion preference.
 726                  $DB->delete_records('forum_discussion_subs', array('id' => $subscription->id));
 727                  unset(self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id]);
 728              } else {
 729                  // The user is already subscribed to the forum. Ignore.
 730                  return false;
 731              }
 732          } else {
 733              if ($subscription) {
 734                  $subscription->preference = time();
 735                  $DB->update_record('forum_discussion_subs', $subscription);
 736              } else {
 737                  $subscription = new \stdClass();
 738                  $subscription->userid  = $userid;
 739                  $subscription->forum = $discussion->forum;
 740                  $subscription->discussion = $discussion->id;
 741                  $subscription->preference = time();
 742  
 743                  $subscription->id = $DB->insert_record('forum_discussion_subs', $subscription);
 744                  self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id] = $subscription->preference;
 745              }
 746          }
 747  
 748          $context = forum_get_context($discussion->forum, $context);
 749          $params = array(
 750              'context' => $context,
 751              'objectid' => $subscription->id,
 752              'relateduserid' => $userid,
 753              'other' => array(
 754                  'forumid' => $discussion->forum,
 755                  'discussion' => $discussion->id,
 756              ),
 757  
 758          );
 759          $event  = event\discussion_subscription_created::create($params);
 760          $event->trigger();
 761  
 762          return true;
 763      }
 764      /**
 765       * Unsubscribes the user from the specified discussion.
 766       *
 767       * @param int $userid The userid of the user being unsubscribed
 768       * @param \stdClass $discussion The discussion to unsubscribe from
 769       * @param \context_module|null $context Module context, may be omitted if not known or if called for the current
 770       *     module set in page.
 771       * @return boolean Whether a change was made
 772       */
 773      public static function unsubscribe_user_from_discussion($userid, $discussion, $context = null) {
 774          global $DB;
 775  
 776          // First check whether the user's subscription preference for this discussion.
 777          $subscription = $DB->get_record('forum_discussion_subs', array('userid' => $userid, 'discussion' => $discussion->id));
 778          if ($subscription) {
 779              if ($subscription->preference == self::FORUM_DISCUSSION_UNSUBSCRIBED) {
 780                  // The user is already unsubscribed from the discussion. Ignore.
 781                  return false;
 782              }
 783          }
 784          // No discussion-level preference. Check for a forum level subscription.
 785          if (!$DB->record_exists('forum_subscriptions', array('userid' => $userid, 'forum' => $discussion->forum))) {
 786              if ($subscription && $subscription->preference != self::FORUM_DISCUSSION_UNSUBSCRIBED) {
 787                  // The user is not subscribed to the forum, but subscribed from the discussion, delete the discussion subscription.
 788                  $DB->delete_records('forum_discussion_subs', array('id' => $subscription->id));
 789                  unset(self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id]);
 790              } else {
 791                  // The user is not subscribed from the forum. Ignore.
 792                  return false;
 793              }
 794          } else {
 795              if ($subscription) {
 796                  $subscription->preference = self::FORUM_DISCUSSION_UNSUBSCRIBED;
 797                  $DB->update_record('forum_discussion_subs', $subscription);
 798              } else {
 799                  $subscription = new \stdClass();
 800                  $subscription->userid  = $userid;
 801                  $subscription->forum = $discussion->forum;
 802                  $subscription->discussion = $discussion->id;
 803                  $subscription->preference = self::FORUM_DISCUSSION_UNSUBSCRIBED;
 804  
 805                  $subscription->id = $DB->insert_record('forum_discussion_subs', $subscription);
 806              }
 807              self::$forumdiscussioncache[$userid][$discussion->forum][$discussion->id] = $subscription->preference;
 808          }
 809  
 810          $context = forum_get_context($discussion->forum, $context);
 811          $params = array(
 812              'context' => $context,
 813              'objectid' => $subscription->id,
 814              'relateduserid' => $userid,
 815              'other' => array(
 816                  'forumid' => $discussion->forum,
 817                  'discussion' => $discussion->id,
 818              ),
 819  
 820          );
 821          $event  = event\discussion_subscription_deleted::create($params);
 822          $event->trigger();
 823  
 824          return true;
 825      }
 826  
 827  }

Search This Site: