diff --git a/enrol/self/lib.php b/enrol/self/lib.php index 1252b060132..a125a4c1272 100644 --- a/enrol/self/lib.php +++ b/enrol/self/lib.php @@ -231,7 +231,7 @@ class enrol_self_plugin extends enrol_plugin { * @return bool|string true if successful, else error message or false. */ public function can_self_enrol(stdClass $instance, $checkuserenrolment = true) { - global $CFG, $DB, $OUTPUT, $USER; + global $DB, $OUTPUT, $USER; if ($checkuserenrolment) { if (isguestuser()) { @@ -244,8 +244,10 @@ class enrol_self_plugin extends enrol_plugin { } } - if ($instance->status != ENROL_INSTANCE_ENABLED) { - return get_string('canntenrol', 'enrol_self'); + // Check if self enrolment is available right now for users. + $result = $this->is_self_enrol_available($instance); + if ($result !== true) { + return $result; } // Check if user has the capability to enrol in this context. @@ -253,6 +255,23 @@ class enrol_self_plugin extends enrol_plugin { return get_string('canntenrol', 'enrol_self'); } + return true; + } + + /** + * Does this plugin support some way to self enrol? + * This function doesn't check user capabilities. Use can_self_enrol to check capabilities. + * + * @param stdClass $instance enrolment instance + * @return bool - true means "Enrol me in this course" link could be available + */ + public function is_self_enrol_available(stdClass $instance) { + global $CFG, $DB, $USER; + + if ($instance->status != ENROL_INSTANCE_ENABLED) { + return get_string('canntenrol', 'enrol_self'); + } + if ($instance->enrolstartdate != 0 and $instance->enrolstartdate > time()) { return get_string('canntenrolearly', 'enrol_self', userdate($instance->enrolstartdate)); } diff --git a/enrol/self/tests/self_test.php b/enrol/self/tests/self_test.php index 99deb277c24..600c1ba10a3 100644 --- a/enrol/self/tests/self_test.php +++ b/enrol/self/tests/self_test.php @@ -630,6 +630,137 @@ class self_test extends \advanced_testcase { $this->assertSame($expectederrorstring, $selfplugin->can_self_enrol($instance1, true)); } + /** + * Test is_self_enrol_available function behavior. + * + * @covers ::is_self_enrol_available + */ + public function test_is_self_enrol_available() { + global $DB, $CFG; + + $this->resetAfterTest(); + $this->preventResetByRollback(); // Messaging does not like transactions... + + $selfplugin = enrol_get_plugin('self'); + + $user1 = $this->getDataGenerator()->create_user(); + $user2 = $this->getDataGenerator()->create_user(); + + $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); + $course = $this->getDataGenerator()->create_course(); + $cohort1 = $this->getDataGenerator()->create_cohort(); + $cohort2 = $this->getDataGenerator()->create_cohort(); + + // New enrolments are allowed and enrolment instance is enabled. + $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST); + $instance->customint6 = 1; + $DB->update_record('enrol', $instance); + $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED); + $this->setUser($user1); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + + $canntenrolerror = get_string('canntenrol', 'enrol_self'); + + // New enrolments are not allowed, but enrolment instance is enabled. + $instance->customint6 = 0; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + + // New enrolments are allowed, but enrolment instance is disabled. + $instance->customint6 = 1; + $DB->update_record('enrol', $instance); + $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED); + $this->setUser($user1); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + + // New enrolments are not allowed and enrolment instance is disabled. + $instance->customint6 = 0; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + + // Enable enrolment instance for the rest of the tests. + $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED); + + // Enrol start date is in future. + $instance->customint6 = 1; + $instance->enrolstartdate = time() + 60; + $DB->update_record('enrol', $instance); + $error = get_string('canntenrolearly', 'enrol_self', userdate($instance->enrolstartdate)); + $this->setUser($user1); + $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance)); + + // Enrol start date is in past. + $instance->enrolstartdate = time() - 60; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + + // Enrol end date is in future. + $instance->enrolstartdate = 0; + $instance->enrolenddate = time() + 60; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + + // Enrol end date is in past. + $instance->enrolenddate = time() - 60; + $DB->update_record('enrol', $instance); + $error = get_string('canntenrollate', 'enrol_self', userdate($instance->enrolenddate)); + $this->setUser($user1); + $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance)); + + // Maximum enrolments reached. + $instance->customint3 = 1; + $instance->enrolenddate = 0; + $DB->update_record('enrol', $instance); + $selfplugin->enrol_user($instance, $user2->id, $studentrole->id); + $error = get_string('maxenrolledreached', 'enrol_self'); + $this->setUser($user1); + $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance)); + + // Maximum enrolments not reached. + $instance->customint3 = 3; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertTrue($selfplugin->is_self_enrol_available($instance)); + + require_once("$CFG->dirroot/cohort/lib.php"); + cohort_add_member($cohort1->id, $user2->id); + + // Cohort test. + $instance->customint5 = $cohort1->id; + $DB->update_record('enrol', $instance); + $error = get_string('cohortnonmemberinfo', 'enrol_self', $cohort1->name); + $this->setUser($user1); + $this->assertStringContainsString($error, $selfplugin->is_self_enrol_available($instance)); + $this->setGuestUser(); + $this->assertStringContainsString($error, $selfplugin->is_self_enrol_available($instance)); + $this->setUser($user2); + $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance)); + } + /** * Test enrol_self_check_group_enrolment_key */ diff --git a/enrol/tests/enrollib_test.php b/enrol/tests/enrollib_test.php index 2f1d91404ff..f033f57e208 100644 --- a/enrol/tests/enrollib_test.php +++ b/enrol/tests/enrollib_test.php @@ -1581,4 +1581,134 @@ class enrollib_test extends advanced_testcase { $this->assertTrue((int)$secondrun > (int)$firstrun); } + /** + * Test enrol_selfenrol_available function behavior. + * + * @covers ::enrol_selfenrol_available + */ + public function test_enrol_selfenrol_available() { + global $DB, $CFG; + + $this->resetAfterTest(); + $this->preventResetByRollback(); // Messaging does not like transactions... + + $selfplugin = enrol_get_plugin('self'); + + $user1 = $this->getDataGenerator()->create_user(); + $user2 = $this->getDataGenerator()->create_user(); + + $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); + $course = $this->getDataGenerator()->create_course(); + $cohort1 = $this->getDataGenerator()->create_cohort(); + $cohort2 = $this->getDataGenerator()->create_cohort(); + + // New enrolments are allowed and enrolment instance is enabled. + $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST); + $instance->customint6 = 1; + $DB->update_record('enrol', $instance); + $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED); + $this->setUser($user1); + $this->assertTrue(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertTrue(enrol_selfenrol_available($course->id)); + + $canntenrolerror = get_string('canntenrol', 'enrol_self'); + + // New enrolments are not allowed, but enrolment instance is enabled. + $instance->customint6 = 0; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + + // New enrolments are allowed, but enrolment instance is disabled. + $instance->customint6 = 1; + $DB->update_record('enrol', $instance); + $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + + // New enrolments are not allowed and enrolment instance is disabled. + $instance->customint6 = 0; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + + // Enable enrolment instance for the rest of the tests. + $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED); + + // Enrol start date is in future. + $instance->customint6 = 1; + $instance->enrolstartdate = time() + 60; + $DB->update_record('enrol', $instance); + $error = get_string('canntenrolearly', 'enrol_self', userdate($instance->enrolstartdate)); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + + // Enrol start date is in past. + $instance->enrolstartdate = time() - 60; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertTrue(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertTrue(enrol_selfenrol_available($course->id)); + + // Enrol end date is in future. + $instance->enrolstartdate = 0; + $instance->enrolenddate = time() + 60; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertTrue(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertTrue(enrol_selfenrol_available($course->id)); + + // Enrol end date is in past. + $instance->enrolenddate = time() - 60; + $DB->update_record('enrol', $instance); + $error = get_string('canntenrollate', 'enrol_self', userdate($instance->enrolenddate)); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + + // Maximum enrolments reached. + $instance->customint3 = 1; + $instance->enrolenddate = 0; + $DB->update_record('enrol', $instance); + $selfplugin->enrol_user($instance, $user2->id, $studentrole->id); + $error = get_string('maxenrolledreached', 'enrol_self'); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + + // Maximum enrolments not reached. + $instance->customint3 = 3; + $DB->update_record('enrol', $instance); + $this->setUser($user1); + $this->assertTrue(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertTrue(enrol_selfenrol_available($course->id)); + + require_once("$CFG->dirroot/cohort/lib.php"); + cohort_add_member($cohort1->id, $user2->id); + + // Cohort test. + $instance->customint5 = $cohort1->id; + $DB->update_record('enrol', $instance); + $error = get_string('cohortnonmemberinfo', 'enrol_self', $cohort1->name); + $this->setUser($user1); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setGuestUser(); + $this->assertFalse(enrol_selfenrol_available($course->id)); + $this->setUser($user2); + $this->assertFalse(enrol_selfenrol_available($course->id)); + } } diff --git a/enrol/upgrade.txt b/enrol/upgrade.txt index cc7d5eb806a..3ac64afd31d 100644 --- a/enrol/upgrade.txt +++ b/enrol/upgrade.txt @@ -1,6 +1,10 @@ This files describes API changes in /enrol/* - plugins, information provided here is intended especially for developers. +=== 4.2 === + +* New is_self_enrol_available() function has been created. Similar to can_self_enrol but without checking user capabilities. + === 4.0 === * Final deprecation of the following webservice: diff --git a/lib/enrollib.php b/lib/enrollib.php index 8f1cb302cac..62d984bd70a 100644 --- a/lib/enrollib.php +++ b/lib/enrollib.php @@ -1235,7 +1235,12 @@ function enrol_selfenrol_available($courseid) { if ($instance->enrol === 'guest') { continue; } - if ($plugins[$instance->enrol]->show_enrolme_link($instance)) { + if ((isguestuser() || !isloggedin()) && + ($plugins[$instance->enrol]->is_self_enrol_available($instance) === true)) { + $result = true; + break; + } + if ($plugins[$instance->enrol]->show_enrolme_link($instance) === true) { $result = true; break; } @@ -2011,6 +2016,17 @@ abstract class enrol_plugin { return false; } + /** + * Does this plugin support some way to self enrol? + * This function doesn't check user capabilities. Use can_self_enrol to check capabilities. + * + * @param stdClass $instance enrolment instance + * @return bool - true means "Enrol me in this course" link could be available. + */ + public function is_self_enrol_available(stdClass $instance) { + return false; + } + /** * Attempt to automatically enrol current user in course without any interaction, * calling code has to make sure the plugin and instance are active. diff --git a/mod/forum/templates/discussion_list.mustache b/mod/forum/templates/discussion_list.mustache index 1758dcd289b..bc379943683 100644 --- a/mod/forum/templates/discussion_list.mustache +++ b/mod/forum/templates/discussion_list.mustache @@ -62,13 +62,13 @@ {{/forum.capabilities.create}} {{^forum.capabilities.create}} {{#forum.capabilities.selfenrol}} -