diff --git a/mod/forum/classes/subscriptions.php b/mod/forum/classes/subscriptions.php index 8f7aa2fea65..ada9b4d9e96 100644 --- a/mod/forum/classes/subscriptions.php +++ b/mod/forum/classes/subscriptions.php @@ -825,4 +825,39 @@ class subscriptions { return true; } + /** + * Gets the default subscription value for the logged in user. + * + * @param \stdClass $forum The forum record + * @param \context $context The course context + * @param \cm_info $cm cm_info + * @param int|null $discussionid The discussion we are checking against + * @return bool Default subscription + * @throws coding_exception + */ + public static function get_user_default_subscription($forum, $context, $cm, $discussionid = null) { + global $USER; + $manageactivities = has_capability('moodle/course:manageactivities', $context); + if (self::subscription_disabled($forum) && !$manageactivities) { + // User does not have permission to subscribe to this discussion at all. + $discussionsubscribe = false; + } else if (self::is_forcesubscribed($forum)) { + // User does not have permission to unsubscribe from this discussion at all. + $discussionsubscribe = true; + } else { + if (isset($discussion) && self::is_subscribed($USER->id, $forum, $discussionid, $cm)) { + // User is subscribed to the discussion - continue the subscription. + $discussionsubscribe = true; + } else if (!isset($discussionid) && self::is_subscribed($USER->id, $forum, null, $cm)) { + // Starting a new discussion, and the user is subscribed to the forum - subscribe to the discussion. + $discussionsubscribe = true; + } else { + // User is not subscribed to either forum or discussion. Follow user preference. + $discussionsubscribe = $USER->autosubscribe ? $USER->autosubscribe : false; + } + } + + return $discussionsubscribe; + } + } diff --git a/mod/forum/externallib.php b/mod/forum/externallib.php index a92d3bd5b05..6a0aaa0b19b 100644 --- a/mod/forum/externallib.php +++ b/mod/forum/externallib.php @@ -823,9 +823,14 @@ class mod_forum_external extends external_api { $context = context_module::instance($cm->id); self::validate_context($context); + $coursecontext = \context_course::instance($course->id); + $discussionsubscribe = \mod_forum\subscriptions::get_user_default_subscription($forum, $coursecontext, + $cm, null); + // Validate options. $options = array( - 'discussionsubscribe' => true, + 'discussionsubscribe' => $discussionsubscribe, + 'private' => false, 'inlineattachmentsid' => 0, 'attachmentsid' => null ); @@ -896,9 +901,11 @@ class mod_forum_external extends external_api { $completion->update_state($cm, COMPLETION_COMPLETE); } - $settings = new stdClass(); - $settings->discussionsubscribe = $options['discussionsubscribe']; - forum_post_subscription($settings, $forum, $discussion); + if ($options['discussionsubscribe']) { + $settings = new stdClass(); + $settings->discussionsubscribe = $options['discussionsubscribe']; + forum_post_subscription($settings, $forum, $discussion); + } } else { throw new moodle_exception('couldnotadd', 'forum'); } diff --git a/mod/forum/tests/externallib_test.php b/mod/forum/tests/externallib_test.php index c095db73a22..17a8f02bc71 100644 --- a/mod/forum/tests/externallib_test.php +++ b/mod/forum/tests/externallib_test.php @@ -895,6 +895,92 @@ class mod_forum_external_testcase extends externallib_advanced_testcase { } + /** + * Test add_discussion_post and auto subscription to a discussion. + */ + public function test_add_discussion_post_subscribe_discussion() { + global $USER; + + $this->resetAfterTest(true); + + self::setAdminUser(); + + $user = self::getDataGenerator()->create_user(); + $admin = get_admin(); + // Create course to add the module. + $course = self::getDataGenerator()->create_course(array('groupmode' => VISIBLEGROUPS, 'groupmodeforce' => 0)); + + $this->getDataGenerator()->enrol_user($user->id, $course->id); + + // Forum with tracking off. + $record = new stdClass(); + $record->course = $course->id; + $forum = self::getDataGenerator()->create_module('forum', $record); + $cm = get_coursemodule_from_id('forum', $forum->cmid, 0, false, MUST_EXIST); + + // Add discussions to the forums. + $record = new stdClass(); + $record->course = $course->id; + $record->userid = $admin->id; + $record->forum = $forum->id; + $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); + $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); + + // Try to post as user. + self::setUser($user); + // Enable auto subscribe discussion. + $USER->autosubscribe = true; + // Add a discussion post in a forum discussion where the user is not subscribed (auto-subscribe preference enabled). + mod_forum_external::add_discussion_post($discussion1->firstpost, 'some subject', 'some text here...'); + + $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id); + $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts); + // We receive the discussion and the post. + $this->assertEquals(2, count($posts['posts'])); + // The user should be subscribed to the discussion after adding a discussion post. + $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion1->id, $cm)); + + // Disable auto subscribe discussion. + $USER->autosubscribe = false; + $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion1->id, $cm)); + // Add a discussion post in a forum discussion where the user is subscribed (auto-subscribe preference disabled). + mod_forum_external::add_discussion_post($discussion1->firstpost, 'some subject 1', 'some text here 1...'); + + $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id); + $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts); + // We receive the discussion and the post. + $this->assertEquals(3, count($posts['posts'])); + // The user should still be subscribed to the discussion after adding a discussion post. + $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion1->id, $cm)); + + $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion2->id, $cm)); + // Add a discussion post in a forum discussion where the user is not subscribed (auto-subscribe preference disabled). + mod_forum_external::add_discussion_post($discussion2->firstpost, 'some subject 2', 'some text here 2...'); + + $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id); + $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts); + // We receive the discussion and the post. + $this->assertEquals(2, count($posts['posts'])); + // The user should still not be subscribed to the discussion after adding a discussion post. + $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion2->id, $cm)); + + // Passing a value for the discussionsubscribe option parameter. + $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion2->id, $cm)); + // Add a discussion post in a forum discussion where the user is not subscribed (auto-subscribe preference disabled), + // and the option parameter 'discussionsubscribe' => true in the webservice. + $option = array('name' => 'discussionsubscribe', 'value' => true); + $options[] = $option; + mod_forum_external::add_discussion_post($discussion2->firstpost, 'some subject 2', 'some text here 2...', + $options); + + $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id); + $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts); + // We receive the discussion and the post. + $this->assertEquals(3, count($posts['posts'])); + // The user should now be subscribed to the discussion after adding a discussion post. + $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion2->id, $cm)); + } + /* * Test add_discussion. A basic test since all the API functions are already covered by unit tests. */