Merge branch 'MDL-50995-master' of git://github.com/jleyva/moodle

This commit is contained in:
Andrew Nicols 2015-09-09 16:03:05 +08:00
commit edf84ada39
6 changed files with 241 additions and 2 deletions

View File

@ -1124,6 +1124,7 @@ $services = array(
'mod_forum_get_forums_by_courses',
'mod_forum_get_forum_discussions_paginated',
'mod_forum_get_forum_discussion_posts',
'mod_forum_add_discussion_post',
'core_files_get_files',
'core_message_get_messages',
'core_message_create_contacts',

View File

@ -81,4 +81,13 @@ $functions = array(
'type' => 'write',
'capabilities' => 'mod/forum:viewdiscussion'
),
'mod_forum_add_discussion_post' => array(
'classname' => 'mod_forum_external',
'methodname' => 'add_discussion_post',
'classpath' => 'mod/forum/externallib.php',
'description' => 'Create new posts into an existing discussion.',
'type' => 'write',
'capabilities' => 'mod/forum:replypost'
),
);

View File

@ -965,4 +965,159 @@ class mod_forum_external extends external_api {
);
}
/**
* Returns description of method parameters
*
* @return external_function_parameters
* @since Moodle 3.0
*/
public static function add_discussion_post_parameters() {
return new external_function_parameters(
array(
'postid' => new external_value(PARAM_INT, 'the post id we are going to reply to
(can be the initial discussion post'),
'subject' => new external_value(PARAM_TEXT, 'new post subject'),
'message' => new external_value(PARAM_RAW, 'new post message (only html format allowed)'),
'options' => new external_multiple_structure (
new external_single_structure(
array(
'name' => new external_value(PARAM_ALPHANUM,
'The allowed keys (value format) are:
discussionsubscribe (bool); subscribe to the discussion?, default to true
'),
'value' => new external_value(PARAM_RAW, 'the value of the option,
this param is validated in the external function.'
)
)
), 'Options', VALUE_DEFAULT, array())
)
);
}
/**
* Create new posts into an existing discussion.
*
* @param int $postid the post id we are going to reply to
* @param string $subject new post subject
* @param string $message new post message (only html format allowed)
* @param array $options optional settings
* @return array of warnings and the new post id
* @since Moodle 3.0
* @throws moodle_exception
*/
public static function add_discussion_post($postid, $subject, $message, $options = array()) {
global $DB, $CFG, $USER;
require_once($CFG->dirroot . "/mod/forum/lib.php");
$params = self::validate_parameters(self::add_discussion_post_parameters(),
array(
'postid' => $postid,
'subject' => $subject,
'message' => $message,
'options' => $options
));
// Validate options.
$options = array(
'discussionsubscribe' => true
);
foreach ($params['options'] as $option) {
$name = trim($option['name']);
switch ($name) {
case 'discussionsubscribe':
$value = clean_param($option['value'], PARAM_BOOL);
break;
default:
throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
}
$options[$name] = $value;
}
$warnings = array();
if (! $parent = forum_get_post_full($params['postid'])) {
throw new moodle_exception('invalidparentpostid', 'forum');
}
if (! $discussion = $DB->get_record("forum_discussions", array("id" => $parent->discussion))) {
throw new moodle_exception('notpartofdiscussion', 'forum');
}
// Request and permission validation.
$forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum');
$context = context_module::instance($cm->id);
self::validate_context($context);
if (!forum_user_can_post($forum, $discussion, $USER, $cm, $course, $context)) {
throw new moodle_exception('nopostforum', 'forum');
}
$thresholdwarning = forum_check_throttling($forum, $cm);
forum_check_blocking_threshold($thresholdwarning);
// Create the post.
$post = new stdClass();
$post->discussion = $discussion->id;
$post->parent = $parent->id;
$post->subject = $params['subject'];
$post->message = $params['message'];
$post->messageformat = FORMAT_HTML; // Force formatting for now.
$post->messagetrust = trusttext_trusted($context);
$post->itemid = 0;
if ($postid = forum_add_new_post($post, null)) {
$post->id = $postid;
// Trigger events and completion.
$params = array(
'context' => $context,
'objectid' => $post->id,
'other' => array(
'discussionid' => $discussion->id,
'forumid' => $forum->id,
'forumtype' => $forum->type,
)
);
$event = \mod_forum\event\post_created::create($params);
$event->add_record_snapshot('forum_posts', $post);
$event->add_record_snapshot('forum_discussions', $discussion);
$event->trigger();
// Update completion state.
$completion = new completion_info($course);
if ($completion->is_enabled($cm) &&
($forum->completionreplies || $forum->completionposts)) {
$completion->update_state($cm, COMPLETION_COMPLETE);
}
$settings = new stdClass();
$settings->discussionsubscribe = $options['discussionsubscribe'];
forum_post_subscription($settings, $forum, $discussion);
} else {
throw new moodle_exception('couldnotadd', 'forum');
}
$result = array();
$result['postid'] = $postid;
$result['warnings'] = $warnings;
return $result;
}
/**
* Returns description of method result value
*
* @return external_description
* @since Moodle 3.0
*/
public static function add_discussion_post_returns() {
return new external_single_structure(
array(
'postid' => new external_value(PARAM_INT, 'new post id'),
'warnings' => new external_warnings()
)
);
}
}

View File

@ -762,4 +762,78 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
$this->assertCount(0, $discussions['warnings']);
}
/**
* Test add_discussion_post
*/
public function test_add_discussion_post() {
global $CFG;
$this->resetAfterTest(true);
$user = self::getDataGenerator()->create_user();
$otheruser = self::getDataGenerator()->create_user();
self::setAdminUser();
// Create course to add the module.
$course = self::getDataGenerator()->create_course(array('groupmode' => VISIBLEGROUPS, 'groupmodeforce' => 0));
// 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);
$forumcontext = context_module::instance($forum->cmid);
// Add discussions to the forums.
$record = new stdClass();
$record->course = $course->id;
$record->userid = $user->id;
$record->forum = $forum->id;
$discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
// Try to post (user not enrolled).
self::setUser($user);
try {
mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
$this->fail('Exception expected due to being unenrolled from the course.');
} catch (moodle_exception $e) {
$this->assertEquals('requireloginerror', $e->errorcode);
}
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$this->getDataGenerator()->enrol_user($otheruser->id, $course->id);
$post = mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
$post = external_api::clean_returnvalue(mod_forum_external::add_discussion_post_returns(), $post);
$posts = mod_forum_external::get_forum_discussion_posts($discussion->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']));
$this->assertEquals($post['postid'], $posts['posts'][1]['id']);
$this->assertEquals('some subject', $posts['posts'][1]['subject']);
$this->assertEquals('some text here...', $posts['posts'][1]['message']);
// Check not posting in groups the user is not member of.
$group = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
groups_add_member($group->id, $otheruser->id);
$forum = self::getDataGenerator()->create_module('forum', $record, array('groupmode' => SEPARATEGROUPS));
$record->forum = $forum->id;
$record->userid = $otheruser->id;
$record->groupid = $group->id;
$discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
try {
mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
$this->fail('Exception expected due to invalid permissions for posting.');
} catch (moodle_exception $e) {
// Expect debugging since we are switching context, and this is something WS_SERVER mode don't like.
$this->assertDebuggingCalled();
$this->assertEquals('nopostforum', $e->errorcode);
}
}
}

View File

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051101; // The current module version (Date: YYYYMMDDXX)
$plugin->version = 2015051102; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'mod_forum'; // Full name of the plugin (used for diagnostics)

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2015090803.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2015090900.00; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.