'message_airnotifier_is_system_configured',
'message_airnotifier_are_notification_preferences_configured',
'core_grades_get_grades',
- 'core_grades_update_grades'),
+ 'core_grades_update_grades',
+ 'mod_forum_get_forums_by_courses',
+ 'mod_forum_get_forum_discussions',
+ 'mod_forum_get_forum_discussion_posts'),
'enabled' => 0,
'restrictedusers' => 0,
'shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE,
'description' => 'Returns a list of forum discussions contained within a given set of forums.',
'type' => 'read',
'capabilities' => 'mod/forum:viewdiscussion, mod/forum:viewqandawithoutposting'
+ ),
+
+ 'mod_forum_get_forum_discussion_posts' => array(
+ 'classname' => 'mod_forum_external',
+ 'methodname' => 'get_forum_discussion_posts',
+ 'classpath' => 'mod/forum/externallib.php',
+ 'description' => 'Returns a list of forum posts for a discussion.',
+ 'type' => 'read',
+ 'capabilities' => 'mod/forum:viewdiscussion, mod/forum:viewqandawithoutposting'
)
);
)
);
}
+
+ /**
+ * Describes the parameters for get_forum_discussion_posts.
+ *
+ * @return external_external_function_parameters
+ * @since Moodle 2.7
+ */
+ public static function get_forum_discussion_posts_parameters() {
+ return new external_function_parameters (
+ array(
+ 'discussionid' => new external_value(PARAM_INT, 'discussion ID', VALUE_REQUIRED),
+ 'sortby' => new external_value(PARAM_ALPHA,
+ 'sort by this element: id, created or modified', VALUE_DEFAULT, 'created'),
+ 'sortdirection' => new external_value(PARAM_ALPHA, 'sort direction: ASC or DESC', VALUE_DEFAULT, 'DESC')
+ )
+ );
+ }
+
+ /**
+ * Returns a list of forum posts for a discussion
+ *
+ * @param int $discussionid the post ids
+ * @param string $sortby sort by this element (id, created or modified)
+ * @param string $sortdirection sort direction: ASC or DESC
+ *
+ * @return array the forum post details
+ * @since Moodle 2.7
+ */
+ public static function get_forum_discussion_posts($discussionid, $sortby = "id", $sortdirection = "ASC") {
+ global $CFG, $DB, $USER;
+
+ $warnings = array();
+
+ // Validate the parameter.
+ $params = self::validate_parameters(self::get_forum_discussion_posts_parameters(),
+ array(
+ 'discussionid' => $discussionid,
+ 'sortby' => $sortby,
+ 'sortdirection' => $sortdirection));
+
+ // Compact/extract functions are not recommended.
+ $discussionid = $params['discussionid'];
+ $sortby = $params['sortby'];
+ $sortdirection = $params['sortdirection'];
+
+ $sortallowedvalues = array('id', 'created', 'modified');
+ if (!in_array($sortby, $sortallowedvalues)) {
+ throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $sortby . '),' .
+ 'allowed values are: ' . implode(',', $sortallowedvalues));
+ }
+
+ $sortdirection = strtoupper($sortdirection);
+ $directionallowedvalues = array('ASC', 'DESC');
+ if (!in_array($sortdirection, $directionallowedvalues)) {
+ throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' .
+ 'allowed values are: ' . implode(',', $directionallowedvalues));
+ }
+
+ $discussion = $DB->get_record('forum_discussions', array('id' => $discussionid), '*', MUST_EXIST);
+ $forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
+ $course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST);
+ $cm = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST);
+
+ // Validate the module context. It checks everything that affects the module visibility (including groupings, etc..).
+ $modcontext = context_module::instance($cm->id);
+ self::validate_context($modcontext);
+
+ // This require must be here, see mod/forum/discuss.php.
+ require_once($CFG->dirroot . "/mod/forum/lib.php");
+
+ // Check they have the view forum capability.
+ require_capability('mod/forum:viewdiscussion', $modcontext, null, true, 'noviewdiscussionspermission', 'forum');
+
+ if (! $post = forum_get_post_full($discussion->firstpost)) {
+ throw new moodle_exception('notexists', 'forum');
+ }
+
+ // This function check groups, qanda, timed discussions, etc.
+ if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) {
+ throw new moodle_exception('noviewdiscussionspermission', 'forum');
+ }
+
+ $canviewfullname = has_capability('moodle/site:viewfullnames', $modcontext);
+
+ // We will add this field in the response.
+ $canreply = forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext);
+
+ $forumtracked = forum_tp_is_tracked($forum);
+
+ $sort = 'p.' . $sortby . ' ' . $sortdirection;
+ $posts = forum_get_all_discussion_posts($discussion->id, $sort, $forumtracked);
+
+ foreach ($posts as $pid => $post) {
+
+ if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) {
+ $warning = array();
+ $warning['item'] = 'post';
+ $warning['itemid'] = $post->id;
+ $warning['warningcode'] = '1';
+ $warning['message'] = 'You can\'t see this post';
+ $warnings[] = $warning;
+ continue;
+ }
+
+ // Function forum_get_all_discussion_posts adds postread field.
+ if (!isset($post->postread)) {
+ $posts[$pid]->postread = false;
+ }
+ $posts[$pid]->canreply = $canreply;
+ $posts[$pid]->children = array();
+ if (!empty($posts[$pid]->children)) {
+ $posts[$pid]->children = array_keys($posts[$pid]->children);
+ }
+
+ $user = new stdclass();
+ $user = username_load_fields_from_object($user, $post);
+ $posts[$pid]->userfullname = fullname($user, $canviewfullname);
+
+ $posts[$pid] = (array) $post;
+ }
+
+ $result = array();
+ $result['posts'] = $posts;
+ $result['warnings'] = $warnings;
+ return $result;
+ }
+
+ /**
+ * Describes the get_forum_discussion_posts return value.
+ *
+ * @return external_single_structure
+ * @since Moodle 2.7
+ */
+ public static function get_forum_discussion_posts_returns() {
+ return new external_single_structure(
+ array(
+ 'posts' => new external_multiple_structure(
+ new external_single_structure(
+ array(
+ 'id' => new external_value(PARAM_INT, 'Post id'),
+ 'discussion' => new external_value(PARAM_INT, 'Discussion id'),
+ 'parent' => new external_value(PARAM_INT, 'Parent id'),
+ 'userid' => new external_value(PARAM_INT, 'User id'),
+ 'created' => new external_value(PARAM_INT, 'Creation time'),
+ 'modified' => new external_value(PARAM_INT, 'Time modified'),
+ 'mailed' => new external_value(PARAM_INT, 'Mailed?'),
+ 'subject' => new external_value(PARAM_TEXT, 'The post subject'),
+ 'message' => new external_value(PARAM_RAW, 'The post message'),
+ 'messageformat' => new external_value(PARAM_INT, 'The post message format'),
+ 'messagetrust' => new external_value(PARAM_INT, 'Can we trust?'),
+ 'attachment' => new external_value(PARAM_RAW, 'Attachments'),
+ 'totalscore' => new external_value(PARAM_INT, 'The post message total score'),
+ 'mailnow' => new external_value(PARAM_INT, 'Mail now?'),
+ 'children' => new external_multiple_structure(new external_value(PARAM_INT, 'children post id')),
+ 'canreply' => new external_value(PARAM_BOOL, 'The user can reply to posts?'),
+ 'postread' => new external_value(PARAM_BOOL, 'The post was read'),
+ 'userfullname' => new external_value(PARAM_TEXT, 'Post author full name')
+ ), 'post'
+ )
+ ),
+ 'warnings' => new external_warnings()
+ )
+ );
+ }
+
}
$this->assertEquals('requireloginerror', $e->errorcode);
}
}
+
+ /**
+ * Test get forum posts
+ */
+ public function test_mod_forum_get_forum_discussion_posts() {
+ global $CFG;
+
+ $this->resetAfterTest(true);
+
+ // Set the CFG variable to allow track forums.
+ $CFG->forum_trackreadposts = true;
+
+ // Create a user who can track forums.
+ $record = new stdClass();
+ $record->trackforums = true;
+ $user1 = self::getDataGenerator()->create_user($record);
+ // Create a bunch of other users to post.
+ $user2 = self::getDataGenerator()->create_user();
+ $user3 = self::getDataGenerator()->create_user();
+
+ // Set the first created user to the test user.
+ self::setUser($user1);
+
+ // Create course to add the module.
+ $course1 = self::getDataGenerator()->create_course();
+
+ // Forum with tracking off.
+ $record = new stdClass();
+ $record->course = $course1->id;
+ $record->trackingtype = FORUM_TRACKING_OFF;
+ $forum1 = self::getDataGenerator()->create_module('forum', $record);
+ $forum1context = context_module::instance($forum1->cmid);
+
+ // Add discussions to the forums.
+ $record = new stdClass();
+ $record->course = $course1->id;
+ $record->userid = $user1->id;
+ $record->forum = $forum1->id;
+ $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
+
+ $record = new stdClass();
+ $record->course = $course1->id;
+ $record->userid = $user2->id;
+ $record->forum = $forum1->id;
+ $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
+
+ // Add 2 replies to the discussion 1 from different users.
+ $record = new stdClass();
+ $record->discussion = $discussion1->id;
+ $record->parent = $discussion1->firstpost;
+ $record->userid = $user2->id;
+ $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
+
+ $record->parent = $discussion1reply1->id;
+ $record->userid = $user3->id;
+ $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
+
+ // Enrol the user in the course.
+ $enrol = enrol_get_plugin('manual');
+ // Following line enrol and assign default role id to the user.
+ // So the user automatically gets mod/forum:viewdiscussion on all forums of the course.
+ $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
+ $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
+ $this->getDataGenerator()->enrol_user($user3->id, $course1->id);
+
+ // Create what we expect to be returned when querying the discussion.
+ $expectedposts = array(
+ 'posts' => array(),
+ 'warnings' => array(),
+ );
+ $expectedposts['posts'][] = array(
+ 'id' => $discussion1reply2->id,
+ 'discussion' => $discussion1reply2->discussion,
+ 'parent' => $discussion1reply2->parent,
+ 'userid' => $discussion1reply2->userid,
+ 'created' => $discussion1reply2->created,
+ 'modified' => $discussion1reply2->modified,
+ 'mailed' => $discussion1reply2->mailed,
+ 'subject' => $discussion1reply2->subject,
+ 'message' => file_rewrite_pluginfile_urls($discussion1reply2->message, 'pluginfile.php',
+ $forum1context->id, 'mod_forum', 'post', $discussion1reply2->id),
+ 'messageformat' => $discussion1reply2->messageformat,
+ 'messagetrust' => $discussion1reply2->messagetrust,
+ 'attachment' => $discussion1reply2->attachment,
+ 'totalscore' => $discussion1reply2->totalscore,
+ 'mailnow' => $discussion1reply2->mailnow,
+ 'children' => array(),
+ 'canreply' => true,
+ 'postread' => false,
+ 'userfullname' => fullname($user3)
+ );
+ $expectedposts['posts'][] = array(
+ 'id' => $discussion1reply1->id,
+ 'discussion' => $discussion1reply1->discussion,
+ 'parent' => $discussion1reply1->parent,
+ 'userid' => $discussion1reply1->userid,
+ 'created' => $discussion1reply1->created,
+ 'modified' => $discussion1reply1->modified,
+ 'mailed' => $discussion1reply1->mailed,
+ 'subject' => $discussion1reply1->subject,
+ 'message' => file_rewrite_pluginfile_urls($discussion1reply1->message, 'pluginfile.php',
+ $forum1context->id, 'mod_forum', 'post', $discussion1reply1->id),
+ 'messageformat' => $discussion1reply1->messageformat,
+ 'messagetrust' => $discussion1reply1->messagetrust,
+ 'attachment' => $discussion1reply1->attachment,
+ 'totalscore' => $discussion1reply1->totalscore,
+ 'mailnow' => $discussion1reply1->mailnow,
+ 'children' => array(),
+ 'canreply' => true,
+ 'postread' => false,
+ 'userfullname' => fullname($user2)
+ );
+
+ // Test a discussion with two additional posts (total 3 posts).
+ $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id, 'modified', 'DESC');
+ $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
+ $this->assertEquals(3, count($posts['posts']));
+
+ // Unset the initial discussion post.
+ array_pop($posts['posts']);
+ $this->assertEquals($expectedposts, $posts);
+
+ // Test discussion without additional posts. There should be only one post (the one created by the discussion).
+ $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id, 'modified', 'DESC');
+ $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
+ $this->assertEquals(1, count($posts['posts']));
+
+ }
}
$record['modified'] = $time;
}
+ if (!isset($record['mailed'])) {
+ $record['mailed'] = 1;
+ }
+
+ if (!isset($record['messageformat'])) {
+ $record['messageformat'] = 1;
+ }
+
+ if (!isset($record['messagetrust'])) {
+ $record['messagetrust'] = 1;
+ }
+
+ if (!isset($record['attachment'])) {
+ $record['attachment'] = "";
+ }
+
+ if (!isset($record['totalscore'])) {
+ $record['totalscore'] = 0;
+ }
+
+ if (!isset($record['mailnow'])) {
+ $record['mailnow'] = 0;
+ }
+
$record = (object) $record;
// Add the post.