Merge branch 'MDL-64254-master' of git://github.com/jleyva/moodle
This commit is contained in:
@@ -195,4 +195,28 @@ $functions = array(
|
||||
'ajax' => true,
|
||||
'capabilities' => 'mod/forum:viewdiscussion, mod/forum:viewqandawithoutposting',
|
||||
),
|
||||
'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)
|
||||
),
|
||||
'mod_forum_prepare_draft_area_for_post' => array(
|
||||
'classname' => 'mod_forum_external',
|
||||
'methodname' => 'prepare_draft_area_for_post',
|
||||
'classpath' => 'mod/forum/externallib.php',
|
||||
'description' => 'Prepares a draft area for editing a post.',
|
||||
'type' => 'write',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
'mod_forum_update_discussion_post' => array(
|
||||
'classname' => 'mod_forum_external',
|
||||
'methodname' => 'update_discussion_post',
|
||||
'classpath' => 'mod/forum/externallib.php',
|
||||
'description' => 'Updates a post or a discussion topic post.',
|
||||
'type' => 'write',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2292,4 +2292,454 @@ class mod_forum_external extends external_api {
|
||||
'warnings' => new external_warnings(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.8
|
||||
*/
|
||||
public static function prepare_draft_area_for_post_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'postid' => new external_value(PARAM_INT, 'Post to prepare the draft area for.'),
|
||||
'area' => new external_value(PARAM_ALPHA, 'Area to prepare: attachment or post.'),
|
||||
'draftitemid' => new external_value(PARAM_INT, 'The draft item id to use. 0 to generate one.',
|
||||
VALUE_DEFAULT, 0),
|
||||
'filestokeep' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'filename' => new external_value(PARAM_FILE, 'File name.'),
|
||||
'filepath' => new external_value(PARAM_PATH, 'File path.'),
|
||||
)
|
||||
), 'Only keep these files in the draft file area. Empty for keeping all.', VALUE_DEFAULT, []
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a draft area for editing a post.
|
||||
*
|
||||
* @param int $postid post to prepare the draft area for
|
||||
* @param string $area area to prepare attachment or post
|
||||
* @param int $draftitemid the draft item id to use. 0 to generate a new one.
|
||||
* @param array $filestokeep only keep these files in the draft file area. Empty for keeping all.
|
||||
* @return array of files in the area, the area options and the draft item id
|
||||
* @since Moodle 3.8
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function prepare_draft_area_for_post($postid, $area, $draftitemid = 0, $filestokeep = []) {
|
||||
global $USER;
|
||||
|
||||
$params = self::validate_parameters(
|
||||
self::prepare_draft_area_for_post_parameters(),
|
||||
array(
|
||||
'postid' => $postid,
|
||||
'area' => $area,
|
||||
'draftitemid' => $draftitemid,
|
||||
'filestokeep' => $filestokeep,
|
||||
)
|
||||
);
|
||||
$directionallowedvalues = ['ASC', 'DESC'];
|
||||
|
||||
$allowedareas = ['attachment', 'post'];
|
||||
if (!in_array($params['area'], $allowedareas)) {
|
||||
throw new invalid_parameter_exception('Invalid value for area parameter
|
||||
(value: ' . $params['area'] . '),' . 'allowed values are: ' . implode(', ', $allowedareas));
|
||||
}
|
||||
|
||||
$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');
|
||||
}
|
||||
|
||||
$context = $forumentity->get_context();
|
||||
self::validate_context($context);
|
||||
|
||||
$managerfactory = mod_forum\local\container::get_manager_factory();
|
||||
$capabilitymanager = $managerfactory->get_capability_manager($forumentity);
|
||||
|
||||
if (!$capabilitymanager->can_edit_post($USER, $discussionentity, $postentity)) {
|
||||
throw new moodle_exception('noviewdiscussionspermission', 'forum');
|
||||
}
|
||||
|
||||
if ($params['area'] == 'attachment') {
|
||||
$legacydatamapperfactory = mod_forum\local\container::get_legacy_data_mapper_factory();
|
||||
$forumdatamapper = $legacydatamapperfactory->get_forum_data_mapper();
|
||||
$forum = $forumdatamapper->to_legacy_object($forumentity);
|
||||
|
||||
$areaoptions = mod_forum_post_form::attachment_options($forum);
|
||||
$messagetext = null;
|
||||
} else {
|
||||
$areaoptions = mod_forum_post_form::editor_options($context, $postentity->get_id());
|
||||
$messagetext = $postentity->get_message();
|
||||
}
|
||||
|
||||
$draftitemid = empty($params['draftitemid']) ? 0 : $params['draftitemid'];
|
||||
$messagetext = file_prepare_draft_area($draftitemid, $context->id, 'mod_forum', $params['area'],
|
||||
$postentity->get_id(), $areaoptions, $messagetext);
|
||||
|
||||
// Just get a structure compatible with external API.
|
||||
array_walk($areaoptions, function(&$item, $key) {
|
||||
$item = ['name' => $key, 'value' => $item];
|
||||
});
|
||||
|
||||
// Do we need to keep only the given files?
|
||||
$usercontext = context_user::instance($USER->id);
|
||||
if (!empty($params['filestokeep'])) {
|
||||
$fs = get_file_storage();
|
||||
|
||||
if ($areafiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid)) {
|
||||
$filestokeep = [];
|
||||
foreach ($params['filestokeep'] as $ftokeep) {
|
||||
$filestokeep[$ftokeep['filepath']][$ftokeep['filename']] = $ftokeep;
|
||||
}
|
||||
|
||||
foreach ($areafiles as $file) {
|
||||
if ($file->is_directory()) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($filestokeep[$file->get_filepath()][$file->get_filename()])) {
|
||||
$file->delete(); // Not in the list to be kept.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'draftitemid' => $draftitemid,
|
||||
'files' => external_util::get_area_files($usercontext->id, 'user', 'draft',
|
||||
$draftitemid),
|
||||
'areaoptions' => $areaoptions,
|
||||
'messagetext' => $messagetext,
|
||||
'warnings' => $warnings,
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.8
|
||||
*/
|
||||
public static function prepare_draft_area_for_post_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'draftitemid' => new external_value(PARAM_INT, 'Draft item id for the file area.'),
|
||||
'files' => new external_files('Draft area files.', VALUE_OPTIONAL),
|
||||
'areaoptions' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'name' => new external_value(PARAM_RAW, 'Name of option.'),
|
||||
'value' => new external_value(PARAM_RAW, 'Value of option.'),
|
||||
)
|
||||
), 'Draft file area options.'
|
||||
),
|
||||
'messagetext' => new external_value(PARAM_RAW, 'Message text with URLs rewritten.'),
|
||||
'warnings' => new external_warnings(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.8
|
||||
*/
|
||||
public static function update_discussion_post_parameters() {
|
||||
return new external_function_parameters(
|
||||
[
|
||||
'postid' => new external_value(PARAM_INT, 'Post to be updated. It can be a discussion topic post.'),
|
||||
'subject' => new external_value(PARAM_TEXT, 'Updated post subject', VALUE_DEFAULT, ''),
|
||||
'message' => new external_value(PARAM_RAW, 'Updated post message (HTML assumed if messageformat is not provided)',
|
||||
VALUE_DEFAULT, ''),
|
||||
'messageformat' => new external_format_value('message', VALUE_DEFAULT),
|
||||
'options' => new external_multiple_structure (
|
||||
new external_single_structure(
|
||||
[
|
||||
'name' => new external_value(
|
||||
PARAM_ALPHANUM,
|
||||
'The allowed keys (value format) are:
|
||||
pinned (bool); (only for discussions) whether to pin this discussion or not
|
||||
discussionsubscribe (bool); whether to subscribe to the post or not
|
||||
inlineattachmentsid (int); the draft file area id for inline attachments in the text
|
||||
attachmentsid (int); the draft file area id for attachments'
|
||||
),
|
||||
'value' => new external_value(PARAM_RAW, 'The value of the option.')
|
||||
]
|
||||
),
|
||||
'Configuration options for the post.',
|
||||
VALUE_DEFAULT,
|
||||
[]
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a post or a discussion post topic.
|
||||
*
|
||||
* @param int $postid post to be updated, it can be a discussion topic post.
|
||||
* @param string $subject updated post subject
|
||||
* @param string $message updated post message (HTML assumed if messageformat is not provided)
|
||||
* @param int $messageformat The format of the message, defaults to FORMAT_HTML
|
||||
* @param array $options different configuration options for the post to be updated.
|
||||
* @return array of warnings and the status (true if the post/discussion was deleted)
|
||||
* @since Moodle 3.8
|
||||
* @throws moodle_exception
|
||||
* @todo support more options: timed posts, groups change and tags.
|
||||
*/
|
||||
public static function update_discussion_post($postid, $subject = '', $message = '', $messageformat = FORMAT_HTML,
|
||||
$options = []) {
|
||||
global $CFG, $USER;
|
||||
require_once($CFG->dirroot . "/mod/forum/lib.php");
|
||||
|
||||
$params = self::validate_parameters(self::add_discussion_post_parameters(),
|
||||
[
|
||||
'postid' => $postid,
|
||||
'subject' => $subject,
|
||||
'message' => $message,
|
||||
'options' => $options,
|
||||
'messageformat' => $messageformat,
|
||||
]
|
||||
);
|
||||
$warnings = [];
|
||||
|
||||
// Validate options.
|
||||
$options = [];
|
||||
foreach ($params['options'] as $option) {
|
||||
$name = trim($option['name']);
|
||||
switch ($name) {
|
||||
case 'pinned':
|
||||
$value = clean_param($option['value'], PARAM_BOOL);
|
||||
break;
|
||||
case 'discussionsubscribe':
|
||||
$value = clean_param($option['value'], PARAM_BOOL);
|
||||
break;
|
||||
case 'inlineattachmentsid':
|
||||
$value = clean_param($option['value'], PARAM_INT);
|
||||
break;
|
||||
case 'attachmentsid':
|
||||
$value = clean_param($option['value'], PARAM_INT);
|
||||
break;
|
||||
default:
|
||||
throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
|
||||
}
|
||||
$options[$name] = $value;
|
||||
}
|
||||
|
||||
$managerfactory = mod_forum\local\container::get_manager_factory();
|
||||
$vaultfactory = mod_forum\local\container::get_vault_factory();
|
||||
$forumvault = $vaultfactory->get_forum_vault();
|
||||
$discussionvault = $vaultfactory->get_discussion_vault();
|
||||
$postvault = $vaultfactory->get_post_vault();
|
||||
$legacydatamapperfactory = mod_forum\local\container::get_legacy_data_mapper_factory();
|
||||
$forumdatamapper = $legacydatamapperfactory->get_forum_data_mapper();
|
||||
$discussiondatamapper = $legacydatamapperfactory->get_discussion_data_mapper();
|
||||
$postdatamapper = $legacydatamapperfactory->get_post_data_mapper();
|
||||
|
||||
$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');
|
||||
}
|
||||
$forum = $forumdatamapper->to_legacy_object($forumentity);
|
||||
$capabilitymanager = $managerfactory->get_capability_manager($forumentity);
|
||||
|
||||
$modcontext = $forumentity->get_context();
|
||||
self::validate_context($modcontext);
|
||||
|
||||
if (!$capabilitymanager->can_edit_post($USER, $discussionentity, $postentity)) {
|
||||
throw new moodle_exception('cannotupdatepost', 'forum');
|
||||
}
|
||||
|
||||
// Get the original post.
|
||||
$updatepost = $postdatamapper->to_legacy_object($postentity);
|
||||
$updatepost->itemid = IGNORE_FILE_MERGE;
|
||||
$updatepost->attachments = IGNORE_FILE_MERGE;
|
||||
|
||||
// Prepare the post to be updated.
|
||||
if (!empty($params['subject'])) {
|
||||
$updatepost->subject = $params['subject'];
|
||||
}
|
||||
|
||||
if (!empty($params['message']) && !empty($params['messageformat'])) {
|
||||
$updatepost->message = $params['message'];
|
||||
$updatepost->messageformat = $params['messageformat'];
|
||||
$updatepost->messagetrust = trusttext_trusted($modcontext);
|
||||
// Clean message text.
|
||||
$updatepost = trusttext_pre_edit($updatepost, 'message', $modcontext);
|
||||
}
|
||||
|
||||
if (isset($options['discussionsubscribe'])) {
|
||||
// No need to validate anything here, forum_post_subscription will do.
|
||||
$updatepost->discussionsubscribe = $options['discussionsubscribe'];
|
||||
}
|
||||
|
||||
// When editing first post/discussion.
|
||||
if (!$postentity->has_parent()) {
|
||||
// Defaults for discussion topic posts.
|
||||
$updatepost->name = $discussionentity->get_name();
|
||||
$updatepost->timestart = $discussionentity->get_time_start();
|
||||
$updatepost->timeend = $discussionentity->get_time_end();
|
||||
|
||||
if (isset($options['pinned'])) {
|
||||
if ($capabilitymanager->can_pin_discussions($USER)) {
|
||||
// Can change pinned if we have capability.
|
||||
$updatepost->pinned = !empty($options['pinned']) ? FORUM_DISCUSSION_PINNED : FORUM_DISCUSSION_UNPINNED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($options['inlineattachmentsid'])) {
|
||||
$updatepost->itemid = $options['inlineattachmentsid'];
|
||||
}
|
||||
|
||||
if (isset($options['attachmentsid']) && forum_can_create_attachment($forum, $modcontext)) {
|
||||
$updatepost->attachments = $options['attachmentsid'];
|
||||
}
|
||||
|
||||
// Update the post.
|
||||
$fakemform = $updatepost->id;
|
||||
if (forum_update_post($updatepost, $fakemform)) {
|
||||
$discussion = $discussiondatamapper->to_legacy_object($discussionentity);
|
||||
|
||||
forum_trigger_post_updated_event($updatepost, $discussion, $modcontext, $forum);
|
||||
|
||||
forum_post_subscription(
|
||||
$updatepost,
|
||||
$forum,
|
||||
$discussion
|
||||
);
|
||||
$status = true;
|
||||
} else {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
return [
|
||||
'status' => $status,
|
||||
'warnings' => $warnings,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.8
|
||||
*/
|
||||
public static function update_discussion_post_returns() {
|
||||
return new external_single_structure(
|
||||
[
|
||||
'status' => new external_value(PARAM_BOOL, 'True if the post/discussion was updated, false otherwise.'),
|
||||
'warnings' => new external_warnings()
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3042,6 +3042,38 @@ function forum_add_new_post($post, $mform, $unused = null) {
|
||||
return $post->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger post updated event.
|
||||
*
|
||||
* @param object $post forum post object
|
||||
* @param object $discussion discussion object
|
||||
* @param object $context forum context object
|
||||
* @param object $forum forum object
|
||||
* @since Moodle 3.8
|
||||
* @return void
|
||||
*/
|
||||
function forum_trigger_post_updated_event($post, $discussion, $context, $forum) {
|
||||
global $USER;
|
||||
|
||||
$params = array(
|
||||
'context' => $context,
|
||||
'objectid' => $post->id,
|
||||
'other' => array(
|
||||
'discussionid' => $discussion->id,
|
||||
'forumid' => $forum->id,
|
||||
'forumtype' => $forum->type,
|
||||
)
|
||||
);
|
||||
|
||||
if ($USER->id !== $post->userid) {
|
||||
$params['relateduserid'] = $post->userid;
|
||||
}
|
||||
|
||||
$event = \mod_forum\event\post_updated::create($params);
|
||||
$event->add_record_snapshot('forum_discussions', $discussion);
|
||||
$event->trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a post.
|
||||
*
|
||||
@@ -3095,6 +3127,13 @@ function forum_update_post($newpost, $mform, $unused = null) {
|
||||
|
||||
forum_add_attachment($post, $forum, $cm, $mform);
|
||||
|
||||
if ($forum->type == 'single' && $post->parent == '0') {
|
||||
// Updating first post of single discussion type -> updating forum intro.
|
||||
$forum->intro = $post->message;
|
||||
$forum->timemodified = time();
|
||||
$DB->update_record("forum", $forum);
|
||||
}
|
||||
|
||||
if (isset($newpost->tags)) {
|
||||
core_tag_tag::set_item_tags('mod_forum', 'forum_posts', $post->id, $context, $newpost->tags);
|
||||
}
|
||||
|
||||
+1
-24
@@ -846,12 +846,7 @@ if ($mformpost->is_cancelled()) {
|
||||
print_error("couldnotupdate", "forum", $errordestination);
|
||||
}
|
||||
|
||||
if ('single' == $forumentity->get_type() && !$postentity->has_parent()) {
|
||||
// Updating first post of single discussion type -> updating forum intro.
|
||||
$forum->intro = $updatepost->message;
|
||||
$forum->timemodified = time();
|
||||
$DB->update_record("forum", $forum);
|
||||
}
|
||||
forum_trigger_post_updated_event($post, $discussion, $modcontext, $forum);
|
||||
|
||||
if ($USER->id === $postentity->get_author_id()) {
|
||||
$message .= get_string("postupdated", "forum");
|
||||
@@ -869,24 +864,6 @@ if ($mformpost->is_cancelled()) {
|
||||
$discussionurl = $urlfactory->get_view_post_url_from_post($postentity);
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'context' => $modcontext,
|
||||
'objectid' => $fromform->id,
|
||||
'other' => array(
|
||||
'discussionid' => $discussion->id,
|
||||
'forumid' => $forum->id,
|
||||
'forumtype' => $forum->type,
|
||||
)
|
||||
);
|
||||
|
||||
if ($USER->id !== $postentity->get_author_id()) {
|
||||
$params['relateduserid'] = $postentity->get_author_id();
|
||||
}
|
||||
|
||||
$event = \mod_forum\event\post_updated::create($params);
|
||||
$event->add_record_snapshot('forum_discussions', $discussion);
|
||||
$event->trigger();
|
||||
|
||||
redirect(
|
||||
forum_go_back_to($discussionurl),
|
||||
$message . $subscribemessage,
|
||||
|
||||
@@ -2997,4 +2997,347 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
|
||||
|
||||
$this->assertEquals($expectedposts, $discussions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test prepare_draft_area_for_post a different user post.
|
||||
*/
|
||||
public function test_prepare_draft_area_for_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 = 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);
|
||||
|
||||
// Add some files only in the attachment area.
|
||||
$filename = 'faketxt.txt';
|
||||
$filerecordinline = array(
|
||||
'contextid' => context_module::instance($forum->cmid)->id,
|
||||
'component' => 'mod_forum',
|
||||
'filearea' => 'attachment',
|
||||
'itemid' => $post->id,
|
||||
'filepath' => '/',
|
||||
'filename' => $filename,
|
||||
);
|
||||
$fs = get_file_storage();
|
||||
$fs->create_file_from_string($filerecordinline, 'fake txt contents 1.');
|
||||
$filerecordinline['filename'] = 'otherfaketxt.txt';
|
||||
$fs->create_file_from_string($filerecordinline, 'fake txt contents 2.');
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
// Check attachment area.
|
||||
$result = mod_forum_external::prepare_draft_area_for_post($post->id, 'attachment');
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::prepare_draft_area_for_post_returns(), $result);
|
||||
$this->assertCount(2, $result['files']);
|
||||
$this->assertEquals($filename, $result['files'][0]['filename']);
|
||||
$this->assertCount(5, $result['areaoptions']);
|
||||
$this->assertEmpty($result['messagetext']);
|
||||
|
||||
// Check again using existing draft item id.
|
||||
$result = mod_forum_external::prepare_draft_area_for_post($post->id, 'attachment', $result['draftitemid']);
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::prepare_draft_area_for_post_returns(), $result);
|
||||
$this->assertCount(2, $result['files']);
|
||||
|
||||
// Keep only certain files in the area.
|
||||
$filestokeep = array(array('filename' => $filename, 'filepath' => '/'));
|
||||
$result = mod_forum_external::prepare_draft_area_for_post($post->id, 'attachment', $result['draftitemid'], $filestokeep);
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::prepare_draft_area_for_post_returns(), $result);
|
||||
$this->assertCount(1, $result['files']);
|
||||
$this->assertEquals($filename, $result['files'][0]['filename']);
|
||||
|
||||
// Check editor (post) area.
|
||||
$filerecordinline['filearea'] = 'post';
|
||||
$filerecordinline['filename'] = 'fakeimage.png';
|
||||
$fs->create_file_from_string($filerecordinline, 'fake image.');
|
||||
$result = mod_forum_external::prepare_draft_area_for_post($post->id, 'post');
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::prepare_draft_area_for_post_returns(), $result);
|
||||
$this->assertCount(1, $result['files']);
|
||||
$this->assertEquals($filerecordinline['filename'], $result['files'][0]['filename']);
|
||||
$this->assertCount(5, $result['areaoptions']);
|
||||
$this->assertEquals($post->message, $result['messagetext']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test update_discussion_post with a discussion.
|
||||
*/
|
||||
public function test_update_discussion_post_discussion() {
|
||||
global $DB, $USER;
|
||||
$this->resetAfterTest(true);
|
||||
// Setup test data.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
|
||||
|
||||
$this->setAdminUser();
|
||||
|
||||
// Add a discussion.
|
||||
$record = new stdClass();
|
||||
$record->course = $course->id;
|
||||
$record->userid = $USER->id;
|
||||
$record->forum = $forum->id;
|
||||
$record->pinned = FORUM_DISCUSSION_UNPINNED;
|
||||
$discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
|
||||
|
||||
$subject = 'Hey subject updated';
|
||||
$message = 'Hey message updated';
|
||||
$messageformat = FORMAT_HTML;
|
||||
$options = [
|
||||
['name' => 'pinned', 'value' => true],
|
||||
];
|
||||
|
||||
$result = mod_forum_external::update_discussion_post($discussion->firstpost, $subject, $message, $messageformat,
|
||||
$options);
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::update_discussion_post_returns(), $result);
|
||||
$this->assertTrue($result['status']);
|
||||
|
||||
// Get the post from WS.
|
||||
$result = mod_forum_external::get_discussion_post($discussion->firstpost);
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::get_discussion_post_returns(), $result);
|
||||
$this->assertEquals($subject, $result['post']['subject']);
|
||||
$this->assertEquals($message, $result['post']['message']);
|
||||
$this->assertEquals($messageformat, $result['post']['messageformat']);
|
||||
|
||||
// Get discussion object from DB.
|
||||
$discussion = $DB->get_record('forum_discussions', ['id' => $discussion->id]);
|
||||
$this->assertEquals($subject, $discussion->name); // Check discussion subject.
|
||||
$this->assertEquals(FORUM_DISCUSSION_PINNED, $discussion->pinned); // Check discussion pinned.
|
||||
}
|
||||
|
||||
/**
|
||||
* Test update_discussion_post with a post.
|
||||
*/
|
||||
public function test_update_discussion_post_post() {
|
||||
global $DB, $USER;
|
||||
$this->resetAfterTest(true);
|
||||
// Setup test data.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
|
||||
$cm = get_coursemodule_from_id('forum', $forum->cmid, 0, false, MUST_EXIST);
|
||||
$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);
|
||||
|
||||
$this->setUser($user);
|
||||
// Enable auto subscribe discussion.
|
||||
$USER->autosubscribe = true;
|
||||
|
||||
// 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);
|
||||
|
||||
// Add a post via WS (so discussion subscription works).
|
||||
$result = mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
|
||||
$newpost = $result['post'];
|
||||
$this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion->id, $cm));
|
||||
|
||||
// Add files in the different areas.
|
||||
$draftidattach = file_get_unused_draft_itemid();
|
||||
$filerecordinline = array(
|
||||
'contextid' => context_user::instance($user->id)->id,
|
||||
'component' => 'user',
|
||||
'filearea' => 'draft',
|
||||
'itemid' => $draftidattach,
|
||||
'filepath' => '/',
|
||||
'filename' => 'faketxt.txt',
|
||||
);
|
||||
$fs = get_file_storage();
|
||||
$fs->create_file_from_string($filerecordinline, 'fake txt contents 1.');
|
||||
|
||||
// Create files in post area (inline).
|
||||
$draftidinlineattach = file_get_unused_draft_itemid();
|
||||
$filerecordinline['itemid'] = $draftidinlineattach;
|
||||
$filerecordinline['filename'] = 'fakeimage.png';
|
||||
$fs->create_file_from_string($filerecordinline, 'img...');
|
||||
|
||||
// Do not update subject.
|
||||
$message = 'Hey message updated';
|
||||
$messageformat = FORMAT_HTML;
|
||||
$options = [
|
||||
['name' => 'discussionsubscribe', 'value' => false],
|
||||
['name' => 'inlineattachmentsid', 'value' => $draftidinlineattach],
|
||||
['name' => 'attachmentsid', 'value' => $draftidattach],
|
||||
];
|
||||
|
||||
$result = mod_forum_external::update_discussion_post($newpost->id, '', $message, $messageformat, $options);
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::update_discussion_post_returns(), $result);
|
||||
$this->assertTrue($result['status']);
|
||||
// Check subscription status.
|
||||
$this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion->id, $cm));
|
||||
|
||||
// Get the post from WS.
|
||||
$result = mod_forum_external::get_forum_discussion_posts($discussion->id);
|
||||
$result = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $result);
|
||||
$found = false;
|
||||
foreach ($result['posts'] as $post) {
|
||||
if ($post['id'] == $newpost->id) {
|
||||
$this->assertEquals($newpost->subject, $post['subject']);
|
||||
$this->assertEquals($message, $post['message']);
|
||||
$this->assertEquals($messageformat, $post['messageformat']);
|
||||
$this->assertCount(1, $post['messageinlinefiles']);
|
||||
$this->assertEquals('fakeimage.png', $post['messageinlinefiles'][0]['filename']);
|
||||
$this->assertCount(1, $post['attachments']);
|
||||
$this->assertEquals('faketxt.txt', $post['attachments'][0]['filename']);
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($found);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test update_discussion_post with other user post (no permissions).
|
||||
*/
|
||||
public function test_update_discussion_post_other_user_post() {
|
||||
global $DB, $USER;
|
||||
$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);
|
||||
|
||||
$this->setAdminUser();
|
||||
// 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);
|
||||
|
||||
// Add a post.
|
||||
$record = new stdClass();
|
||||
$record->course = $course->id;
|
||||
$record->userid = $USER->id;
|
||||
$record->forum = $forum->id;
|
||||
$record->discussion = $discussion->id;
|
||||
$record->parent = $discussion->firstpost;
|
||||
$newpost = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
|
||||
|
||||
$this->setUser($user);
|
||||
$subject = 'Hey subject updated';
|
||||
$message = 'Hey message updated';
|
||||
$messageformat = FORMAT_HTML;
|
||||
|
||||
$this->expectExceptionMessage(get_string('cannotupdatepost', 'forum'));
|
||||
mod_forum_external::update_discussion_post($newpost->id, $subject, $message, $messageformat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2019100105; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2019100106; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2019051100; // Requires this Moodle version
|
||||
$plugin->component = 'mod_forum'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
Reference in New Issue
Block a user