MDL-51568 self_enrol: New Web Service enrol_self_enrol_user
authorJuan Leyva <juanleyvadelgado@gmail.com>
Mon, 28 Sep 2015 12:04:04 +0000 (14:04 +0200)
committerJuan Leyva <juanleyvadelgado@gmail.com>
Mon, 12 Oct 2015 07:13:51 +0000 (09:13 +0200)
enrol/self/db/services.php
enrol/self/externallib.php
enrol/self/locallib.php
enrol/self/tests/externallib_test.php
enrol/self/tests/self_test.php
enrol/self/version.php
lib/db/services.php
version.php

index dd50355..506defd 100644 (file)
@@ -30,5 +30,13 @@ $functions = array(
         'classpath'   => 'enrol/self/externallib.php',
         'description' => 'self enrolment instance information.',
         'type'        => 'read'
+    ),
+
+    'enrol_self_enrol_user' => array(
+        'classname'   => 'enrol_self_external',
+        'methodname'  => 'enrol_user',
+        'classpath'   => 'enrol/self/externallib.php',
+        'description' => 'Self enrol the current user in the given course.',
+        'type'        => 'write'
     )
 );
index 4451087..ad61b0c 100644 (file)
@@ -97,4 +97,158 @@ class enrol_self_external extends external_api {
             )
         );
     }
+
+    /**
+     * Returns description of method parameters
+     *
+     * @return external_function_parameters
+     * @since Moodle 3.0
+     */
+    public static function enrol_user_parameters() {
+        return new external_function_parameters(
+            array(
+                'courseid' => new external_value(PARAM_INT, 'Id of the course'),
+                'password' => new external_value(PARAM_RAW, 'Enrolment key', VALUE_DEFAULT, ''),
+                'instanceid' => new external_value(PARAM_INT, 'Instance id of self enrolment plugin.', VALUE_DEFAULT, 0)
+            )
+        );
+    }
+
+    /**
+     * Self enrol the current user in the given course.
+     *
+     * @param int $courseid id of course
+     * @param string $password enrolment key
+     * @param int $instanceid instance id of self enrolment plugin
+     * @return array of warnings and status result
+     * @since Moodle 3.0
+     * @throws moodle_exception
+     */
+    public static function enrol_user($courseid, $password = '', $instanceid = 0) {
+        global $CFG;
+
+        require_once($CFG->libdir . '/enrollib.php');
+
+        $params = self::validate_parameters(self::enrol_user_parameters(),
+                                            array(
+                                                'courseid' => $courseid,
+                                                'password' => $password,
+                                                'instanceid' => $instanceid
+                                            ));
+
+        $warnings = array();
+
+        $course = get_course($params['courseid']);
+        $context = context_course::instance($course->id);
+        // Note that we can't use validate_context because the user is not enrolled in the course.
+        require_login(null, false, null, false, true);
+
+        if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $context)) {
+            throw new moodle_exception('coursehidden');
+        }
+
+        // Retrieve the self enrolment plugin.
+        $enrol = enrol_get_plugin('self');
+        if (empty($enrol)) {
+            throw new moodle_exception('canntenrol', 'enrol_self');
+        }
+
+        // We can expect multiple self-enrolment instances.
+        $instances = array();
+        $enrolinstances = enrol_get_instances($course->id, true);
+        foreach ($enrolinstances as $courseenrolinstance) {
+            if ($courseenrolinstance->enrol == "self") {
+                // Instance specified.
+                if (!empty($params['instanceid'])) {
+                    if ($courseenrolinstance->id == $params['instanceid']) {
+                        $instances[] = $courseenrolinstance;
+                        break;
+                    }
+                } else {
+                    $instances[] = $courseenrolinstance;
+                }
+
+            }
+        }
+        if (empty($instances)) {
+            throw new moodle_exception('canntenrol', 'enrol_self');
+        }
+
+        // Try to enrol the user in the instance/s.
+        $enrolled = false;
+        foreach ($instances as $instance) {
+            $enrolstatus = $enrol->can_self_enrol($instance);
+            if ($enrolstatus === true) {
+                if ($instance->password and $params['password'] !== $instance->password) {
+
+                    // Check if we are using group enrolment keys.
+                    if ($instance->customint1) {
+                        require_once($CFG->dirroot . "/enrol/self/locallib.php");
+
+                        if (!enrol_self_check_group_enrolment_key($course->id, $params['password'])) {
+                            $warnings[] = array(
+                                'item' => 'instance',
+                                'itemid' => $instance->id,
+                                'warningcode' => '2',
+                                'message' => get_string('passwordinvalid', 'enrol_self')
+                            );
+                            continue;
+                        }
+                    } else {
+                        if ($enrol->get_config('showhint')) {
+                            $hint = core_text::substr($instance->password, 0, 1);
+                            $warnings[] = array(
+                                'item' => 'instance',
+                                'itemid' => $instance->id,
+                                'warningcode' => '3',
+                                'message' => s(get_string('passwordinvalidhint', 'enrol_self', $hint)) // message is PARAM_TEXT.
+                            );
+                            continue;
+                        } else {
+                            $warnings[] = array(
+                                'item' => 'instance',
+                                'itemid' => $instance->id,
+                                'warningcode' => '4',
+                                'message' => get_string('passwordinvalid', 'enrol_self')
+                            );
+                            continue;
+                        }
+                    }
+                }
+
+                // Do the enrolment.
+                $data = array('enrolpassword' => $params['password']);
+                $enrol->enrol_self($instance, (object) $data);
+                $enrolled = true;
+                break;
+            } else {
+                $warnings[] = array(
+                    'item' => 'instance',
+                    'itemid' => $instance->id,
+                    'warningcode' => '1',
+                    'message' => $enrolstatus
+                );
+            }
+        }
+
+        $result = array();
+        $result['status'] = $enrolled;
+        $result['warnings'] = $warnings;
+        return $result;
+    }
+
+    /**
+     * Returns description of method result value
+     *
+     * @return external_description
+     * @since Moodle 3.0
+     */
+    public static function enrol_user_returns() {
+        return new external_single_structure(
+            array(
+                'status' => new external_value(PARAM_BOOL, 'status: true if the user is enrolled, false otherwise'),
+                'warnings' => new external_warnings()
+            )
+        );
+    }
 }
index 226555d..a60224e 100644 (file)
@@ -26,6 +26,32 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once("$CFG->libdir/formslib.php");
 
+/**
+ * Check if the given password match a group enrolment key in the specified course.
+ *
+ * @param  int $courseid            course id
+ * @param  string $enrolpassword    enrolment password
+ * @return bool                     True if match
+ * @since  Moodle 3.0
+ */
+function enrol_self_check_group_enrolment_key($courseid, $enrolpassword) {
+    global $DB;
+
+    $found = false;
+    $groups = $DB->get_records('groups', array('courseid' => $courseid), 'id ASC', 'id, enrolmentkey');
+
+    foreach ($groups as $group) {
+        if (empty($group->enrolmentkey)) {
+            continue;
+        }
+        if ($group->enrolmentkey === $enrolpassword) {
+            $found = true;
+            break;
+        }
+    }
+    return $found;
+}
+
 class enrol_self_enrol_form extends moodleform {
     protected $instance;
     protected $toomany = false;
@@ -103,18 +129,8 @@ class enrol_self_enrol_form extends moodleform {
         if ($instance->password) {
             if ($data['enrolpassword'] !== $instance->password) {
                 if ($instance->customint1) {
-                    $groups = $DB->get_records('groups', array('courseid'=>$instance->courseid), 'id ASC', 'id, enrolmentkey');
-                    $found = false;
-                    foreach ($groups as $group) {
-                        if (empty($group->enrolmentkey)) {
-                            continue;
-                        }
-                        if ($group->enrolmentkey === $data['enrolpassword']) {
-                            $found = true;
-                            break;
-                        }
-                    }
-                    if (!$found) {
+                    // Check group enrolment key.
+                    if (!enrol_self_check_group_enrolment_key($instance->courseid, $data['enrolpassword'])) {
                         // We can not hint because there are probably multiple passwords.
                         $errors['enrolpassword'] = get_string('passwordinvalid', 'enrol_self');
                     }
index d4abbe2..74b1cbe 100644 (file)
@@ -96,4 +96,147 @@ class enrol_self_external_testcase extends externallib_advanced_testcase {
         $this->assertTrue($instanceinfo3['status']);
         $this->assertEquals(get_string('password', 'enrol_self'), $instanceinfo3['enrolpassword']);
     }
+
+    /**
+     * Test enrol_user
+     */
+    public function test_enrol_user() {
+        global $DB;
+
+        self::resetAfterTest(true);
+
+        $user = self::getDataGenerator()->create_user();
+        self::setUser($user);
+
+        $course1 = self::getDataGenerator()->create_course();
+        $course2 = self::getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+        $user3 = self::getDataGenerator()->create_user();
+        $user4 = self::getDataGenerator()->create_user();
+
+        $context1 = context_course::instance($course1->id);
+        $context2 = context_course::instance($course2->id);
+
+        $selfplugin = enrol_get_plugin('self');
+        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
+        $instance1id = $selfplugin->add_instance($course1, array('status' => ENROL_INSTANCE_ENABLED,
+                                                                'name' => 'Test instance 1',
+                                                                'customint6' => 1,
+                                                                'roleid' => $studentrole->id));
+        $instance2id = $selfplugin->add_instance($course2, array('status' => ENROL_INSTANCE_DISABLED,
+                                                                'customint6' => 1,
+                                                                'name' => 'Test instance 2',
+                                                                'roleid' => $studentrole->id));
+        $instance1 = $DB->get_record('enrol', array('id' => $instance1id), '*', MUST_EXIST);
+        $instance2 = $DB->get_record('enrol', array('id' => $instance2id), '*', MUST_EXIST);
+
+        self::setUser($user1);
+
+        // Self enrol me.
+        $result = enrol_self_external::enrol_user($course1->id);
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+
+        self::assertTrue($result['status']);
+        self::assertEquals(1, $DB->count_records('user_enrolments', array('enrolid' => $instance1->id)));
+        self::assertTrue(is_enrolled($context1, $user1));
+
+        // Add password.
+        $instance2->password = 'abcdef';
+        $DB->update_record('enrol', $instance2);
+
+        // Try instance not enabled.
+        try {
+            enrol_self_external::enrol_user($course2->id);
+        } catch (moodle_exception $e) {
+            self::assertEquals('canntenrol', $e->errorcode);
+        }
+
+        // Enable the instance.
+        $selfplugin->update_status($instance2, ENROL_INSTANCE_ENABLED);
+
+        // Try not passing a key.
+        $result = enrol_self_external::enrol_user($course2->id);
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertFalse($result['status']);
+        self::assertCount(1, $result['warnings']);
+        self::assertEquals('4', $result['warnings'][0]['warningcode']);
+
+        // Try passing an invalid key.
+        $result = enrol_self_external::enrol_user($course2->id, 'invalidkey');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertFalse($result['status']);
+        self::assertCount(1, $result['warnings']);
+        self::assertEquals('4', $result['warnings'][0]['warningcode']);
+
+        // Try passing an invalid key with hint.
+        $selfplugin->set_config('showhint', true);
+        $result = enrol_self_external::enrol_user($course2->id, 'invalidkey');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertFalse($result['status']);
+        self::assertCount(1, $result['warnings']);
+        self::assertEquals('3', $result['warnings'][0]['warningcode']);
+
+        // Everything correct, now.
+        $result = enrol_self_external::enrol_user($course2->id, 'abcdef');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+
+        self::assertTrue($result['status']);
+        self::assertEquals(1, $DB->count_records('user_enrolments', array('enrolid' => $instance2->id)));
+        self::assertTrue(is_enrolled($context2, $user1));
+
+        // Try group password now, other user.
+        $instance2->customint1 = 1;
+        $instance2->password = 'zyx';
+        $DB->update_record('enrol', $instance2);
+
+        $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course2->id));
+        $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course2->id, 'enrolmentkey' => 'zyx'));
+
+        self::setUser($user2);
+        // Try passing and invalid key for group.
+        $result = enrol_self_external::enrol_user($course2->id, 'invalidkey');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertFalse($result['status']);
+        self::assertCount(1, $result['warnings']);
+        self::assertEquals('2', $result['warnings'][0]['warningcode']);
+
+        // Now, everything ok.
+        $result = enrol_self_external::enrol_user($course2->id, 'zyx');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+
+        self::assertTrue($result['status']);
+        self::assertEquals(2, $DB->count_records('user_enrolments', array('enrolid' => $instance2->id)));
+        self::assertTrue(is_enrolled($context2, $user2));
+
+        // Try multiple instances now, multiple errors.
+        $instance3id = $selfplugin->add_instance($course2, array('status' => ENROL_INSTANCE_ENABLED,
+                                                                'customint6' => 1,
+                                                                'name' => 'Test instance 2',
+                                                                'roleid' => $studentrole->id));
+        $instance3 = $DB->get_record('enrol', array('id' => $instance3id), '*', MUST_EXIST);
+        $instance3->password = 'abcdef';
+        $DB->update_record('enrol', $instance3);
+
+        self::setUser($user3);
+        $result = enrol_self_external::enrol_user($course2->id, 'invalidkey');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertFalse($result['status']);
+        self::assertCount(2, $result['warnings']);
+
+        // Now, everything ok.
+        $result = enrol_self_external::enrol_user($course2->id, 'zyx');
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertTrue($result['status']);
+        self::assertTrue(is_enrolled($context2, $user3));
+
+        // Now test passing an instance id.
+        self::setUser($user4);
+        $result = enrol_self_external::enrol_user($course2->id, 'abcdef', $instance3id);
+        $result = external_api::clean_returnvalue(enrol_self_external::enrol_user_returns(), $result);
+        self::assertTrue($result['status']);
+        self::assertTrue(is_enrolled($context2, $user3));
+        self::assertCount(0, $result['warnings']);
+        self::assertEquals(1, $DB->count_records('user_enrolments', array('enrolid' => $instance3->id)));
+    }
 }
index b4250c0..b695600 100644 (file)
@@ -614,4 +614,41 @@ class enrol_self_testcase extends advanced_testcase {
         $this->setUser($user1);
         $this->assertSame($expectederrorstring, $selfplugin->can_self_enrol($instance1, true));
     }
+
+    /**
+     * Test enrol_self_check_group_enrolment_key
+     */
+    public function test_enrol_self_check_group_enrolment_key() {
+        global $DB;
+        self::resetAfterTest(true);
+
+        // Test in course with groups.
+        $course = self::getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
+
+        $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
+        $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'enrolmentkey' => 'thepassword'));
+
+        $result = enrol_self_check_group_enrolment_key($course->id, 'invalidpassword');
+        $this->assertFalse($result);
+
+        $result = enrol_self_check_group_enrolment_key($course->id, 'thepassword');
+        $this->assertTrue($result);
+
+        // Test disabling group options.
+        $course->groupmode = NOGROUPS;
+        $course->groupmodeforce = 0;
+        $DB->update_record('course', $course);
+
+        $result = enrol_self_check_group_enrolment_key($course->id, 'invalidpassword');
+        $this->assertFalse($result);
+
+        $result = enrol_self_check_group_enrolment_key($course->id, 'thepassword');
+        $this->assertTrue($result);
+
+        // Test without groups.
+        $othercourse = self::getDataGenerator()->create_course();
+        $result = enrol_self_check_group_enrolment_key($othercourse->id, 'thepassword');
+        $this->assertFalse($result);
+
+    }
 }
index 5e89b6c..e5933e0 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2015051100;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2015051101;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2015050500;        // Requires this Moodle version
 $plugin->component = 'enrol_self';      // Full name of the plugin (used for diagnostics)
 $plugin->cron      = 600;
index 6451e63..effb656 100644 (file)
@@ -1158,6 +1158,7 @@ $services = array(
             'core_calendar_get_calendar_events',
             'core_enrol_get_users_courses',
             'core_enrol_get_enrolled_users',
+            'enrol_self_enrol_user',
             'core_user_get_users_by_id',
             'core_webservice_get_site_info',
             'core_notes_create_notes',
index f810c83..c78bc6a 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2015100800.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2015100800.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.