MDL-64588 comment: New WebService core_comment_add_comment

This commit is contained in:
Juan Leyva 2019-02-13 15:12:33 +01:00 committed by Jake Dallimore
parent 2234b6c9dc
commit 8e4a9ed854
4 changed files with 327 additions and 29 deletions

View File

@ -170,4 +170,119 @@ class core_comment_external extends external_api {
)
);
}
/**
* Helper to get the structure of a single comment.
*
* @return external_single_structure the comment structure.
*/
protected static function get_comment_structure() {
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Comment ID'),
'content' => new external_value(PARAM_RAW, 'The content text formatted'),
'format' => new external_format_value('content'),
'timecreated' => new external_value(PARAM_INT, 'Time created (timestamp)'),
'strftimeformat' => new external_value(PARAM_NOTAGS, 'Time format'),
'profileurl' => new external_value(PARAM_URL, 'URL profile'),
'fullname' => new external_value(PARAM_NOTAGS, 'fullname'),
'time' => new external_value(PARAM_NOTAGS, 'Time in human format'),
'avatar' => new external_value(PARAM_RAW, 'HTML user picture'),
'userid' => new external_value(PARAM_INT, 'User ID'),
'delete' => new external_value(PARAM_BOOL, 'Permission to delete=true/false', VALUE_OPTIONAL)
), 'comment'
);
}
/**
* Returns description of method parameters for the add_comments method.
*
* @return external_function_parameters
*/
public static function add_comments_parameters() {
return new external_function_parameters(
[
'comments' => new external_multiple_structure(
new external_single_structure(
[
'contextlevel' => new external_value(PARAM_ALPHA, 'contextlevel system, course, user...'),
'instanceid' => new external_value(PARAM_INT, 'the id of item associated with the contextlevel'),
'component' => new external_value(PARAM_COMPONENT, 'component'),
'content' => new external_value(PARAM_RAW, 'component'),
'itemid' => new external_value(PARAM_INT, 'associated id'),
'area' => new external_value(PARAM_AREA, 'string comment area', VALUE_DEFAULT, ''),
]
)
)
]
);
}
/**
* Add a comment or comments.
*
* @param array $comments the array of comments to create.
* @return array the array containing those comments created.
* @throws comment_exception
*/
public static function add_comments($comments) {
global $CFG, $SITE;
if (empty($CFG->usecomments)) {
throw new comment_exception('commentsnotenabled', 'moodle');
}
$params = self::validate_parameters(self::add_comments_parameters(), ['comments' => $comments]);
// Validate every intended comment before creating anything, storing the validated comment for use below.
foreach ($params['comments'] as $index => $comment) {
$context = self::get_context_from_params($comment);
self::validate_context($context);
list($context, $course, $cm) = get_context_info_array($context->id);
if ($context->id == SYSCONTEXTID) {
$course = $SITE;
}
// Initialising comment object.
$args = new stdClass();
$args->context = $context;
$args->course = $course;
$args->cm = $cm;
$args->component = $comment['component'];
$args->itemid = $comment['itemid'];
$args->area = $comment['area'];
$manager = new comment($args);
if (!$manager->can_post()) {
throw new comment_exception('nopermissiontocomment');
}
$params['comments'][$index]['preparedcomment'] = $manager;
}
// Create the comments.
$results = [];
foreach ($params['comments'] as $comment) {
$manager = $comment['preparedcomment'];
$newcomment = $manager->add($comment['content']);
if (!empty($newcomment) && is_object($newcomment)) {
$results[] = $newcomment;
}
$newcomment->delete = true; // USER created the comment, so they can delete it.
}
return $results;
}
/**
* Returns description of method result value for the add_comments method.
*
* @return external_description
*/
public static function add_comments_returns() {
return new external_multiple_structure(
self::get_comment_structure()
);
}
}

View File

@ -45,34 +45,25 @@ class core_comment_externallib_testcase extends externallib_advanced_testcase {
* Tests set up
*/
protected function setUp() {
global $CFG;
global $CFG, $DB;
require_once($CFG->dirroot . '/comment/lib.php');
}
/**
* Test get_comments
*/
public function test_get_comments() {
global $DB, $CFG;
$this->resetAfterTest(true);
$CFG->usecomments = true;
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course(array('enablecomment' => 1));
$this->student = $this->getDataGenerator()->create_user();
$this->course = $this->getDataGenerator()->create_course(array('enablecomment' => 1));
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $studentrole->id);
$record = new stdClass();
$record->course = $course->id;
$record->course = $this->course->id;
$record->name = "Mod data test";
$record->intro = "Some intro of some sort";
$record->comments = 1;
$module = $this->getDataGenerator()->create_module('data', $record);
$field = data_get_field_new('text', $module);
$this->module = $this->getDataGenerator()->create_module('data', $record);
$field = data_get_field_new('text', $this->module);
$fielddetail = new stdClass();
$fielddetail->name = 'Name';
@ -80,28 +71,37 @@ class core_comment_externallib_testcase extends externallib_advanced_testcase {
$field->define_field($fielddetail);
$field->insert_field();
$recordid = data_add_record($module);
$this->recordid = data_add_record($this->module);
$datacontent = array();
$datacontent['fieldid'] = $field->field->id;
$datacontent['recordid'] = $recordid;
$datacontent['recordid'] = $this->recordid;
$datacontent['content'] = 'Asterix';
$contentid = $DB->insert_record('data_content', $datacontent);
$cm = get_coursemodule_from_instance('data', $module->id, $course->id);
$this->cm = get_coursemodule_from_instance('data', $this->module->id, $this->course->id);
$context = context_module::instance($module->cmid);
$this->context = context_module::instance($this->module->cmid);
}
$this->setUser($user);
/**
* Test get_comments
*/
public function test_get_comments() {
global $DB;
$this->resetAfterTest(true);
$this->setUser($this->student);
// We need to add the comments manually, the comment API uses the global OUTPUT and this is going to make the WS to fail.
$newcmt = new stdClass;
$newcmt->contextid = $context->id;
$newcmt->contextid = $this->context->id;
$newcmt->commentarea = 'database_entry';
$newcmt->itemid = $recordid;
$newcmt->itemid = $this->recordid;
$newcmt->content = 'New comment';
$newcmt->format = 0;
$newcmt->userid = $user->id;
$newcmt->userid = $this->student->id;
$newcmt->timecreated = time();
$cmtid1 = $DB->insert_record('comments', $newcmt);
@ -110,9 +110,9 @@ class core_comment_externallib_testcase extends externallib_advanced_testcase {
$cmtid2 = $DB->insert_record('comments', $newcmt);
$contextlevel = 'module';
$instanceid = $cm->id;
$instanceid = $this->cm->id;
$component = 'mod_data';
$itemid = $recordid;
$itemid = $this->recordid;
$area = 'database_entry';
$page = 0;
@ -127,8 +127,8 @@ class core_comment_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals(15, $result['perpage']);
$this->assertTrue($result['canpost']);
$this->assertEquals($user->id, $result['comments'][0]['userid']);
$this->assertEquals($user->id, $result['comments'][1]['userid']);
$this->assertEquals($this->student->id, $result['comments'][0]['userid']);
$this->assertEquals($this->student->id, $result['comments'][1]['userid']);
$this->assertEquals($cmtid2, $result['comments'][0]['id']); // Default ordering newer first.
$this->assertEquals($cmtid1, $result['comments'][1]['id']);
@ -154,4 +154,180 @@ class core_comment_externallib_testcase extends externallib_advanced_testcase {
$this->assertEquals($CFG->commentsperpage, $result['perpage']);
$this->assertEquals($cmtid2, $result['comments'][0]['id']);
}
/**
* Test add_comments not enabled site level
*/
public function test_add_comments_not_enabled_site_level() {
global $CFG;
$this->resetAfterTest(true);
$CFG->usecomments = false;
$this->setUser($this->student);
$this->expectException(comment_exception::class);
core_comment_external::add_comments([
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'abc',
'itemid' => $this->recordid,
'area' => 'database_entry'
]
]);
}
/**
* Test add_comments not enabled module level
*/
public function test_add_comments_not_enabled_module_level() {
global $DB;
$this->resetAfterTest(true);
$DB->set_field('data', 'comments', 0, array('id' => $this->module->id));
$this->setUser($this->student);
$this->expectException(comment_exception::class);
core_comment_external::add_comments([
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'abc',
'itemid' => $this->recordid,
'area' => 'database_entry'
]
]);
}
/**
* Test add_comments
*/
public function test_add_comments_single() {
$this->resetAfterTest(true);
$this->setUser($this->student);
$result = core_comment_external::add_comments([
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'abc',
'itemid' => $this->recordid,
'area' => 'database_entry'
]
]);
$result = external_api::clean_returnvalue(core_comment_external::add_comments_returns(), $result);
$expectedkeys = [
'id',
'content',
'format',
'timecreated',
'strftimeformat',
'profileurl',
'fullname',
'time',
'avatar',
'userid',
'delete',
];
// Verify the result contains 1 result having the correct structure.
$this->assertCount(1, $result);
foreach ($expectedkeys as $key) {
$this->assertArrayHasKey($key, $result[0]);
}
}
/**
* Test add_comments when one of the comments contains invalid data and cannot be created.
*
* This simply verifies that the entire operation fails.
*/
public function test_add_comments_multiple_contains_invalid() {
$this->resetAfterTest(true);
$this->setUser($this->student);
$this->expectException(comment_exception::class);
core_comment_external::add_comments([
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'abc',
'itemid' => $this->recordid,
'area' => 'database_entry'
],
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'abc',
'itemid' => $this->recordid,
'area' => 'areanotfound'
],
]);
}
/**
* Test add_comments when one of the comments contains invalid data and cannot be created.
*
* This simply verifies that the entire operation fails.
*/
public function test_add_comments_multiple_all_valid() {
$this->resetAfterTest(true);
$this->setUser($this->student);
$inputdata = [
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'cat',
'itemid' => $this->recordid,
'area' => 'database_entry'
],
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'dog',
'itemid' => $this->recordid,
'area' => 'database_entry'
]
];
$result = core_comment_external::add_comments($inputdata);
$result = external_api::clean_returnvalue(core_comment_external::add_comments_returns(), $result);
// Two comments should have been created.
$this->assertCount(2, $result);
// The content for each comment should come back formatted.
foreach ($result as $index => $comment) {
$formatoptions = array('overflowdiv' => true, 'blanktarget' => true);
$expectedcontent = format_text($inputdata[$index]['content'], FORMAT_MOODLE, $formatoptions);
$this->assertEquals($expectedcontent, $comment['content']);
}
}
/**
* Test add_comments invalid area
*/
public function test_add_comments_invalid_area() {
$this->resetAfterTest(true);
$this->setUser($this->student);
$comments = [
[
'contextlevel' => 'module',
'instanceid' => $this->cm->id,
'component' => 'mod_data',
'content' => 'abc',
'itemid' => $this->recordid,
'area' => 'rhomboid'
]
];
$this->expectException(comment_exception::class);
core_comment_external::add_comments($comments);
}
}

View File

@ -334,6 +334,13 @@ $functions = array(
'capabilities' => 'moodle/comment:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
'core_comment_add_comments' => array(
'classname' => 'core_comment_external',
'methodname' => 'add_comments',
'description' => 'Adds a comment or comments.',
'type' => 'write',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
'core_completion_get_activities_completion_status' => array(
'classname' => 'core_completion_external',
'methodname' => 'get_activities_completion_status',

View File

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