Search moodle.org's
Developer Documentation


  • Bug fixes for general core bugs in 2.8.x ended 9 November 2015 (12 months).
  • Bug fixes for security issues in 2.8.x ended 9 May 2016 (18 months).
  • minimum PHP 5.4.4 (always use latest PHP 5.4.x or 5.5.x on Windows - http://windows.php.net/download/), PHP 7 is NOT supported
  • Differences Between: [Versions 28 and 32] [Versions 28 and 33] [Versions 28 and 34] [Versions 28 and 35] [Versions 28 and 36] [Versions 28 and 37]

       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: