diff --git a/mod/forum/db/services.php b/mod/forum/db/services.php index f6cee741609..9f72919b3e8 100644 --- a/mod/forum/db/services.php +++ b/mod/forum/db/services.php @@ -183,4 +183,12 @@ $functions = array( 'type' => 'write', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), ), + 'mod_forum_get_discussion_post' => array( + 'classname' => 'mod_forum_external', + 'methodname' => 'get_discussion_post', + 'classpath' => 'mod/forum/externallib.php', + 'description' => 'Get a particular discussion post.', + 'type' => 'read', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/forum/externallib.php b/mod/forum/externallib.php index 624e7233cde..8cca27d7063 100644 --- a/mod/forum/externallib.php +++ b/mod/forum/externallib.php @@ -2152,4 +2152,84 @@ class mod_forum_external extends external_api { ) ); } + + /** + * Returns description of method parameters + * + * @return external_function_parameters + * @since Moodle 3.8 + */ + public static function get_discussion_post_parameters() { + return new external_function_parameters( + array( + 'postid' => new external_value(PARAM_INT, 'Post to fetch.'), + ) + ); + } + /** + * Get a particular discussion post. + * + * @param int $postid post to fetch + * @return array of post and warnings (if any) + * @since Moodle 3.8 + * @throws moodle_exception + */ + public static function get_discussion_post($postid) { + global $USER, $CFG; + + $params = self::validate_parameters(self::get_discussion_post_parameters(), + array( + 'postid' => $postid, + )); + $warnings = array(); + $vaultfactory = mod_forum\local\container::get_vault_factory(); + $forumvault = $vaultfactory->get_forum_vault(); + $discussionvault = $vaultfactory->get_discussion_vault(); + $postvault = $vaultfactory->get_post_vault(); + + $postentity = $postvault->get_from_id($params['postid']); + if (empty($postentity)) { + throw new moodle_exception('invalidpostid', 'forum'); + } + $discussionentity = $discussionvault->get_from_id($postentity->get_discussion_id()); + if (empty($discussionentity)) { + throw new moodle_exception('notpartofdiscussion', 'forum'); + } + $forumentity = $forumvault->get_from_id($discussionentity->get_forum_id()); + if (empty($forumentity)) { + throw new moodle_exception('invalidforumid', 'forum'); + } + self::validate_context($forumentity->get_context()); + + $managerfactory = mod_forum\local\container::get_manager_factory(); + $capabilitymanager = $managerfactory->get_capability_manager($forumentity); + + if (!$capabilitymanager->can_view_post($USER, $discussionentity, $postentity)) { + throw new moodle_exception('noviewdiscussionspermission', 'forum'); + } + + $builderfactory = mod_forum\local\container::get_builder_factory(); + $postbuilder = $builderfactory->get_exported_posts_builder(); + $posts = $postbuilder->build($USER, [$forumentity], [$discussionentity], [$postentity]); + $post = empty($posts) ? array() : reset($posts); + + $result = array(); + $result['post'] = $post; + $result['warnings'] = $warnings; + return $result; + } + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 3.8 + */ + public static function get_discussion_post_returns() { + return new external_single_structure( + array( + 'post' => \mod_forum\local\exporters\post::get_read_structure(), + 'warnings' => new external_warnings(), + ) + ); + } } diff --git a/mod/forum/tests/externallib_test.php b/mod/forum/tests/externallib_test.php index 7ee327574a1..f6e81fb5a5c 100644 --- a/mod/forum/tests/externallib_test.php +++ b/mod/forum/tests/externallib_test.php @@ -2604,4 +2604,103 @@ class mod_forum_external_testcase extends externallib_advanced_testcase { $this->expectExceptionMessage(get_string('cannotdeletepost', 'forum')); mod_forum_external::delete_post($post->id); } + + /** + * Test get_discussion_post a discussion. + */ + public function test_get_discussion_post_discussion() { + global $DB; + $this->resetAfterTest(true); + // Setup test data. + $course = $this->getDataGenerator()->create_course(); + $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); + $user = $this->getDataGenerator()->create_user(); + $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); + self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id); + // Add a discussion. + $record = new stdClass(); + $record->course = $course->id; + $record->userid = $user->id; + $record->forum = $forum->id; + $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); + $this->setUser($user); + $result = mod_forum_external::get_discussion_post($discussion->firstpost); + $result = external_api::clean_returnvalue(mod_forum_external::get_discussion_post_returns(), $result); + $this->assertEquals($discussion->firstpost, $result['post']['id']); + $this->assertFalse($result['post']['hasparent']); + $this->assertEquals($discussion->message, $result['post']['message']); + } + + /** + * Test get_discussion_post a post. + */ + public function test_get_discussion_post_post() { + global $DB; + $this->resetAfterTest(true); + // Setup test data. + $course = $this->getDataGenerator()->create_course(); + $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); + $user = $this->getDataGenerator()->create_user(); + $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); + self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id); + // Add a discussion. + $record = new stdClass(); + $record->course = $course->id; + $record->userid = $user->id; + $record->forum = $forum->id; + $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); + $parentpost = $DB->get_record('forum_posts', array('discussion' => $discussion->id)); + // Add a post. + $record = new stdClass(); + $record->course = $course->id; + $record->userid = $user->id; + $record->forum = $forum->id; + $record->discussion = $discussion->id; + $record->parent = $parentpost->id; + $post = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record); + $this->setUser($user); + $result = mod_forum_external::get_discussion_post($post->id); + $result = external_api::clean_returnvalue(mod_forum_external::get_discussion_post_returns(), $result); + $this->assertEquals($post->id, $result['post']['id']); + $this->assertTrue($result['post']['hasparent']); + $this->assertEquals($post->message, $result['post']['message']); + } + + /** + * Test get_discussion_post a different user post. + */ + public function test_get_discussion_post_other_user_post() { + global $DB; + $this->resetAfterTest(true); + // Setup test data. + $course = $this->getDataGenerator()->create_course(); + $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); + $user = $this->getDataGenerator()->create_user(); + $otheruser = $this->getDataGenerator()->create_user(); + $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); + self::getDataGenerator()->enrol_user($user->id, $course->id, $role->id); + self::getDataGenerator()->enrol_user($otheruser->id, $course->id, $role->id); + // Add a discussion. + $record = array(); + $record['course'] = $course->id; + $record['forum'] = $forum->id; + $record['userid'] = $user->id; + $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); + $parentpost = $DB->get_record('forum_posts', array('discussion' => $discussion->id)); + // Add a post. + $record = new stdClass(); + $record->course = $course->id; + $record->userid = $user->id; + $record->forum = $forum->id; + $record->discussion = $discussion->id; + $record->parent = $parentpost->id; + $post = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record); + // Check other user post. + $this->setUser($otheruser); + $result = mod_forum_external::get_discussion_post($post->id); + $result = external_api::clean_returnvalue(mod_forum_external::get_discussion_post_returns(), $result); + $this->assertEquals($post->id, $result['post']['id']); + $this->assertTrue($result['post']['hasparent']); + $this->assertEquals($post->message, $result['post']['message']); + } }