diff --git a/group/externallib.php b/group/externallib.php index 9ed2492e122..cb61dc8f0c6 100644 --- a/group/externallib.php +++ b/group/externallib.php @@ -1486,4 +1486,96 @@ class core_group_external extends external_api { ); } + /** + * Returns description of method parameters + * + * @return external_function_parameters + * @since Moodle 3.6 + */ + public static function update_groups_parameters() { + return new external_function_parameters( + array( + 'groups' => new external_multiple_structure( + new external_single_structure( + array( + 'id' => new external_value(PARAM_INT, 'ID of the group'), + 'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'), + 'description' => new external_value(PARAM_RAW, 'group description text', VALUE_OPTIONAL), + 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT), + 'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase', VALUE_OPTIONAL), + 'idnumber' => new external_value(PARAM_RAW, 'id number', VALUE_OPTIONAL) + ) + ), 'List of group objects. A group is found by the id, then all other details provided will be updated.' + ) + ) + ); + } + + /** + * Update groups + * + * @param array $groups + * @return null + * @since Moodle 3.6 + */ + public static function update_groups($groups) { + global $CFG, $DB; + require_once("$CFG->dirroot/group/lib.php"); + + $params = self::validate_parameters(self::update_groups_parameters(), array('groups' => $groups)); + + $transaction = $DB->start_delegated_transaction(); + + foreach ($params['groups'] as $group) { + $group = (object)$group; + + if (trim($group->name) == '') { + throw new invalid_parameter_exception('Invalid group name'); + } + + if (! $currentgroup = $DB->get_record('groups', array('id' => $group->id))) { + throw new invalid_parameter_exception("Group $group->id does not exist"); + } + + // Check if the modified group name already exists in the course. + if ($group->name != $currentgroup->name and + $DB->get_record('groups', array('courseid' => $currentgroup->courseid, 'name' => $group->name))) { + throw new invalid_parameter_exception('A different group with the same name already exists in the course'); + } + + $group->courseid = $currentgroup->courseid; + + // Now security checks. + $context = context_course::instance($group->courseid); + try { + self::validate_context($context); + } catch (Exception $e) { + $exceptionparam = new sdtClass(); + $exceptionparam->message = $e->getMessage(); + $exceptionparam->courseid = $group->courseid; + throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam); + } + require_capability('moodle/course:managegroups', $context); + + if (!empty($group->description)) { + $group->descriptionformat = external_validate_format($group->descriptionformat); + } + + groups_update_group($group); + } + + $transaction->allow_commit(); + + return null; + } + + /** + * Returns description of method result value + * + * @return null + * @since Moodle 3.6 + */ + public static function update_groups_returns() { + return null; + } } diff --git a/group/tests/externallib_test.php b/group/tests/externallib_test.php index 287118e7b96..e1af7ca62dc 100644 --- a/group/tests/externallib_test.php +++ b/group/tests/externallib_test.php @@ -115,6 +115,85 @@ class core_group_externallib_testcase extends externallib_advanced_testcase { $froups = core_group_external::create_groups(array($group4)); } + /** + * Test update_groups + * + * @expectedException required_capability_exception + */ + public function test_update_groups() { + global $DB; + + $this->resetAfterTest(true); + + $course = self::getDataGenerator()->create_course(); + + $group1data = array(); + $group1data['courseid'] = $course->id; + $group1data['name'] = 'Group Test 1'; + $group1data['description'] = 'Group Test 1 description'; + $group1data['descriptionformat'] = FORMAT_MOODLE; + $group1data['enrolmentkey'] = 'Test group enrol secret phrase'; + $group1data['idnumber'] = 'TEST1'; + $group2data = array(); + $group2data['courseid'] = $course->id; + $group2data['name'] = 'Group Test 2'; + $group2data['description'] = 'Group Test 2 description'; + $group2data['idnumber'] = 'TEST2'; + + // Set the required capabilities by the external function. + $context = context_course::instance($course->id); + $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id); + $this->assignUserCapability('moodle/course:view', $context->id, $roleid); + + // Create the test groups. + $group1 = self::getDataGenerator()->create_group($group1data); + $group2 = self::getDataGenerator()->create_group($group2data); + + $group1data['id'] = $group1->id; + unset($group1data['courseid']); + $group2data['id'] = $group2->id; + unset($group2data['courseid']); + + // No exceptions should be triggered. + $group1data['idnumber'] = 'CHANGED'; + core_group_external::update_groups(array($group1data)); + $group2data['description'] = 'Group Test 2 description CHANGED'; + core_group_external::update_groups(array($group2data)); + + foreach ([$group1, $group2] as $group) { + $dbgroup = $DB->get_record('groups', array('id' => $group->id), '*', MUST_EXIST); + switch ($dbgroup->name) { + case $group1data['name']: + $this->assertEquals($dbgroup->idnumber, $group1data['idnumber']); + $groupdescription = $group1data['description']; + break; + case $group2data['name']: + $this->assertEquals($dbgroup->idnumber, $group2data['idnumber']); + $groupdescription = $group2data['description']; + break; + default: + throw new moodle_exception('unknowngroupname'); + break; + } + $this->assertEquals($dbgroup->description, $groupdescription); + } + + // Taken idnumber exception. + $group1data['idnumber'] = 'TEST2'; + try { + $groups = core_group_external::update_groups(array($group1data)); + $this->fail('Exception expected due to already existing idnumber.'); + } catch (moodle_exception $e) { + $this->assertInstanceOf('moodle_exception', $e); + $this->assertEquals(get_string('idnumbertaken', 'error'), $e->getMessage()); + } + + // Call without required capability. + $group1data['idnumber'] = 'TEST1'; + $this->unassignUserCapability('moodle/course:managegroups', $context->id, $roleid); + $groups = core_group_external::update_groups(array($group1data)); + } + /** * Test get_groups * diff --git a/lib/db/services.php b/lib/db/services.php index 4f41b1ca291..76e705f48cc 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -847,6 +847,14 @@ $functions = array( 'description' => 'Updates existing groupings', 'type' => 'write', ), + 'core_group_update_groups' => array( + 'classname' => 'core_group_external', + 'methodname' => 'update_groups', + 'classpath' => 'group/externallib.php', + 'description' => 'Updates existing groups.', + 'type' => 'write', + 'capabilities' => 'moodle/course:managegroups' + ), 'core_message_block_user' => array( 'classname' => 'core_message_external', 'methodname' => 'block_user', diff --git a/version.php b/version.php index bdfeda5c41a..9d63cbf0692 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2018110300.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2018110500.00; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.