diff --git a/enrol/manual/db/services.php b/enrol/manual/db/services.php index 87e4e305611..85224464225 100644 --- a/enrol/manual/db/services.php +++ b/enrol/manual/db/services.php @@ -44,4 +44,13 @@ $functions = array( 'type' => 'write', ), + 'enrol_manual_unenrol_users' => array( + 'classname' => 'enrol_manual_external', + 'methodname' => 'unenrol_users', + 'classpath' => 'enrol/manual/externallib.php', + 'description' => 'Manual unenrol users', + 'capabilities'=> 'enrol/manual:unenrol', + 'type' => 'write', + ), + ); diff --git a/enrol/manual/externallib.php b/enrol/manual/externallib.php index d24cc1cd650..8a9871d3c04 100644 --- a/enrol/manual/externallib.php +++ b/enrol/manual/externallib.php @@ -156,6 +156,75 @@ class enrol_manual_external extends external_api { return null; } + /** + * Returns description of method parameters. + * + * @return external_function_parameters + */ + public static function unenrol_users_parameters() { + return new external_function_parameters(array( + 'enrolments' => new external_multiple_structure( + new external_single_structure( + array( + 'userid' => new external_value(PARAM_INT, 'The user that is going to be unenrolled'), + 'courseid' => new external_value(PARAM_INT, 'The course to unenrol the user from'), + 'roleid' => new external_value(PARAM_INT, 'The user role', VALUE_OPTIONAL), + ) + ) + ) + )); + } + + /** + * Unenrolment of users. + * + * @param array $enrolments an array of course user and role ids + * @throws coding_exception + * @throws dml_transaction_exception + * @throws invalid_parameter_exception + * @throws moodle_exception + * @throws required_capability_exception + * @throws restricted_context_exception + */ + public static function unenrol_users($enrolments) { + global $CFG, $DB; + $params = self::validate_parameters(self::unenrol_users_parameters(), array('enrolments' => $enrolments)); + require_once($CFG->libdir . '/enrollib.php'); + $transaction = $DB->start_delegated_transaction(); // Rollback all enrolment if an error occurs. + $enrol = enrol_get_plugin('manual'); + if (empty($enrol)) { + throw new moodle_exception('manualpluginnotinstalled', 'enrol_manual'); + } + + foreach ($params['enrolments'] as $enrolment) { + $context = context_course::instance($enrolment['courseid']); + self::validate_context($context); + require_capability('enrol/manual:unenrol', $context); + $instance = $DB->get_record('enrol', array('courseid' => $enrolment['courseid'], 'enrol' => 'manual')); + if (!$instance) { + throw new moodle_exception('wsnoinstance', 'enrol_manual', $enrolment); + } + $user = $DB->get_record('user', array('id' => $enrolment['userid'])); + if (!$user) { + throw new invalid_parameter_exception('User id not exist: '.$enrolment['userid']); + } + if (!$enrol->allow_unenrol($instance)) { + throw new moodle_exception('wscannotunenrol', 'enrol_manual', '', $enrolment); + } + $enrol->unenrol_user($instance, $enrolment['userid']); + } + $transaction->allow_commit(); + } + + /** + * Returns description of method result value. + * + * @return null + */ + public static function unenrol_users_returns() { + return null; + } + } /** diff --git a/enrol/manual/lang/en/enrol_manual.php b/enrol/manual/lang/en/enrol_manual.php index 6c29c6681db..7c5f941e291 100644 --- a/enrol/manual/lang/en/enrol_manual.php +++ b/enrol/manual/lang/en/enrol_manual.php @@ -71,3 +71,4 @@ $string['unenrolusers'] = 'Unenrol users'; $string['wscannotenrol'] = 'Plugin instance cannot manually enrol a user in the course id = {$a->courseid}'; $string['wsnoinstance'] = 'Manual enrolment plugin instance doesn\'t exist or is disabled for the course (id = {$a->courseid})'; $string['wsusercannotassign'] = 'You don\'t have the permission to assign this role ({$a->roleid}) to this user ({$a->userid}) in this course({$a->courseid}).'; +$string['manualpluginnotinstalled'] = 'The "Manual" plugin has not yet been installed'; \ No newline at end of file diff --git a/enrol/manual/tests/externallib_test.php b/enrol/manual/tests/externallib_test.php index 04f9212817d..2eefd4ae4fe 100644 --- a/enrol/manual/tests/externallib_test.php +++ b/enrol/manual/tests/externallib_test.php @@ -114,4 +114,170 @@ class enrol_manual_externallib_testcase extends externallib_advanced_testcase { $this->assertSame('wsnoinstance', $e->errorcode); } } + + /** + * Test for unerolling a single user. + * @throws coding_exception + * @throws invalid_parameter_exception + * @throws moodle_exception + */ + public function test_unenrol_user_single() { + global $CFG, $DB; + require_once($CFG->libdir . '/enrollib.php'); + $this->resetAfterTest(true); + // The user who perform the action. + $user = $this->getDataGenerator()->create_user(); + $this->setUser($user); // Log this user in. + $enrol = enrol_get_plugin('manual'); + // Create a course. + $course = self::getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST); + // Set the capability for the user. + $roleid = $this->assignUserCapability('enrol/manual:enrol', $coursecontext); + $this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid); + $this->assignUserCapability('moodle/course:view', $coursecontext, $roleid); + $this->assignUserCapability('moodle/role:assign', $coursecontext, $roleid); + // Create a student and enrol them into the course. + $student = $this->getDataGenerator()->create_user(); + $enrol->enrol_user($enrolinstance, $student->id); + $this->assertTrue(is_enrolled($coursecontext, $student)); + // Call the web service to unenrol. + enrol_manual_external::unenrol_users(array( + array('userid' => $student->id, 'courseid' => $course->id), + )); + $this->assertFalse(is_enrolled($coursecontext, $student)); + } + + /** + * Test for unenrolling multiple users. + * @throws coding_exception + * @throws invalid_parameter_exception + * @throws moodle_exception + */ + public function test_unenrol_user_multiple() { + global $CFG, $DB; + require_once($CFG->libdir . '/enrollib.php'); + $this->resetAfterTest(true); + // The user who perform the action. + $user = $this->getDataGenerator()->create_user(); + $this->setUser($user); // Log this user in. + // Create a course. + $course = self::getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST); + // Set the capability for the user. + $roleid = $this->assignUserCapability('enrol/manual:enrol', $coursecontext); + $this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid); + $this->assignUserCapability('moodle/course:view', $coursecontext, $roleid); + $this->assignUserCapability('moodle/role:assign', $coursecontext, $roleid); + $enrol = enrol_get_plugin('manual'); + // Create a student and enrol them into the course. + $student1 = $this->getDataGenerator()->create_user(); + $enrol->enrol_user($enrolinstance, $student1->id); + $this->assertTrue(is_enrolled($coursecontext, $student1)); + $student2 = $this->getDataGenerator()->create_user(); + $enrol->enrol_user($enrolinstance, $student2->id); + $this->assertTrue(is_enrolled($coursecontext, $student2)); + // Call the web service to unenrol. + enrol_manual_external::unenrol_users(array( + array('userid' => $student1->id, 'courseid' => $course->id), + array('userid' => $student2->id, 'courseid' => $course->id), + )); + $this->assertFalse(is_enrolled($coursecontext, $student1)); + $this->assertFalse(is_enrolled($coursecontext, $student2)); + } + + /** + * Test for unenrol capability. + * @throws coding_exception + * @throws invalid_parameter_exception + * @throws moodle_exception + */ + public function test_unenrol_user_error_no_capability() { + global $CFG, $DB; + require_once($CFG->libdir . '/enrollib.php'); + $this->resetAfterTest(true); + // The user who perform the action. + $user = $this->getDataGenerator()->create_user(); + $this->setUser($user); // Log this user in. + // Create a course. + $course = self::getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST); + $enrol = enrol_get_plugin('manual'); + // Create a student and enrol them into the course. + $student = $this->getDataGenerator()->create_user(); + $enrol->enrol_user($enrolinstance, $student->id); + $this->assertTrue(is_enrolled($coursecontext, $student)); + // Call the web service to unenrol. + try { + enrol_manual_external::unenrol_users(array( + array('userid' => $student->id, 'courseid' => $course->id), + )); + $this->fail('Exception expected: User cannot log in to the course'); + } catch (Exception $ex) { + $this->assertTrue($ex instanceof require_login_exception); + } + // Set the capability for the course, then try again. + $roleid = $this->assignUserCapability('moodle/course:view', $coursecontext); + try { + enrol_manual_external::unenrol_users(array( + array('userid' => $student->id, 'courseid' => $course->id), + )); + $this->fail('Exception expected: User cannot log in to the course'); + } catch (Exception $ex) { + $this->assertTrue($ex instanceof required_capability_exception); + } + // Assign unenrol capability. + $this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid); + enrol_manual_external::unenrol_users(array( + array('userid' => $student->id, 'courseid' => $course->id), + )); + $this->assertFalse(is_enrolled($coursecontext, $student)); + } + + /** + * Test for unenrol if user does not exist. + * @throws coding_exception + */ + public function test_unenrol_user_error_not_exist() { + global $CFG, $DB; + require_once($CFG->libdir . '/enrollib.php'); + $this->resetAfterTest(true); + // The user who perform the action. + $user = $this->getDataGenerator()->create_user(); + $this->setUser($user); // Log this user in. + $enrol = enrol_get_plugin('manual'); + // Create a course. + $course = self::getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST); + // Set the capability for the user. + $roleid = $this->assignUserCapability('enrol/manual:enrol', $coursecontext); + $this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid); + $this->assignUserCapability('moodle/course:view', $coursecontext, $roleid); + $this->assignUserCapability('moodle/role:assign', $coursecontext, $roleid); + // Create a student and enrol them into the course. + $student = $this->getDataGenerator()->create_user(); + $enrol->enrol_user($enrolinstance, $student->id); + $this->assertTrue(is_enrolled($coursecontext, $student)); + try { + enrol_manual_external::unenrol_users(array( + array('userid' => $student->id + 1, 'courseid' => $course->id), + )); + $this->fail('Exception expected: invalid student id'); + } catch (Exception $ex) { + $this->assertTrue($ex instanceof invalid_parameter_exception); + } + $DB->delete_records('enrol', array('id' => $enrolinstance->id)); + try { + enrol_manual_external::unenrol_users(array( + array('userid' => $student->id + 1, 'courseid' => $course->id), + )); + $this->fail('Exception expected: invalid student id'); + } catch (Exception $ex) { + $this->assertTrue($ex instanceof moodle_exception); + } + } }