diff --git a/classes/plugin.php b/classes/plugin.php index 17a52b6..a80bd6e 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -215,7 +215,7 @@ public function enrol_user( $status = null, $recovergrades = null ) { - global $CFG, $DB; + global $DB; // We need to keep the role of the user. if (isset($instance->roleid)) { $roleid = $instance->roleid; @@ -234,39 +234,6 @@ public function enrol_user( $context = \context_course::instance($instance->courseid, MUST_EXIST); parent::enrol_user($instance, $userid, $roleid, $timestart, $timeend, $status, $recovergrades); role_assign($roleid, $userid, $context->id, 'enrol_coursecompleted', $instance->id); - - // Send welcome message if needed. - if ($instance->customint2 > 0) { - // There is a course welcome message to be sent. - $adhock = new \enrol_coursecompleted\task\send_welcome(); - $adhock->set_custom_data( - [ - 'userid' => $userid, - 'enrolid' => $instance->id, - 'courseid' => $instance->courseid, - 'completedid' => $instance->customint1, - ] - ); - $adhock->set_component('enrol_coursecompleted'); - \core\task\manager::queue_adhoc_task($adhock); - } - - // Keep the user in a group when needed. - if ($instance->customint3 > 0) { - require_once($CFG->dirroot . '/group/lib.php'); - $groups = array_values(groups_get_user_groups($instance->customint1, $userid)); - foreach ($groups as $group) { - $subs = array_values($group); - foreach ($subs as $sub) { - $groupnamea = groups_get_group_name($sub); - $groupnameb = groups_get_group_by_name($instance->courseid, $groupnamea); - if ($groupnameb) { - groups_add_member($groupnameb, $userid); - } - } - } - } - mark_user_dirty($userid); } else { debugging('Role does not exist', DEBUG_DEVELOPER); } diff --git a/classes/task/send_welcome.php b/classes/task/send_welcome.php deleted file mode 100644 index 1278b18..0000000 --- a/classes/task/send_welcome.php +++ /dev/null @@ -1,84 +0,0 @@ -. - -/** - * Process expirations task. - * - * @package enrol_coursecompleted - * @copyright 2020 eWallah (www.eWallah.net) - * @author Renaat Debleu - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace enrol_coursecompleted\task; - -use context_course; -use core_user; -use moodle_url; -use stdClass; - -/** - * Process expirations task. - * - * @package enrol_coursecompleted - * @copyright 2020 eWallah (www.eWallah.net) - * @author Renaat Debleu - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class send_welcome extends \core\task\adhoc_task { - /** - * Execute scheduled task - * - * @return boolean - */ - public function execute() { - global $CFG, $DB; - $data = $this->get_custom_data(); - if ($user = core_user::get_user($data->userid)) { - if ($course = $DB->get_field('course', 'fullname', ['id' => $data->courseid])) { - if ($complcourse = $DB->get_field('course', 'fullname', ['id' => $data->completedid])) { - $context = context_course::instance($data->courseid); - $context2 = context_course::instance($data->completedid); - $a = new stdClass(); - $a->coursename = format_string($course, true, ['context' => $context]); - $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id&course=$data->courseid"; - $a->completed = format_string($complcourse, true, ['context' => $context2]); - $custom = $DB->get_field('enrol', 'customtext1', ['id' => $data->enrolid]); - if ($custom != '') { - $key = ['{$a->coursename}', '{$a->completed}', '{$a->profileurl}', '{$a->fullname}', '{$a->email}']; - $value = [$a->coursename, $a->completed, $a->profileurl, fullname($user), $user->email]; - $message = str_replace($key, $value, $custom); - } else { - $message = get_string('welcometocourse', 'enrol_coursecompleted', $a); - } - if (strpos($message, '<') === false) { - $messagehtml = $message; - } else { - // This is most probably the tag/newline soup known as FORMAT_MOODLE. - $messagehtml = format_text( - $message, - FORMAT_MOODLE, - ['context' => $context, 'para' => false, 'newlines' => true, 'filter' => true] - ); - } - $subject = get_string('welcometocourse', 'moodle', $a->coursename); - // Directly emailing welcome message rather than using messaging. - email_to_user($user, core_user::get_noreply_user(), $subject, $message, $messagehtml); - } - } - } - } -} diff --git a/classes/user_enrolment_callbacks.php b/classes/user_enrolment_callbacks.php new file mode 100644 index 0000000..08223ec --- /dev/null +++ b/classes/user_enrolment_callbacks.php @@ -0,0 +1,84 @@ +. + +namespace enrol_coursecompleted; + +use context_course; +use core_user; +use moodle_url; +use stdClass; + +/** + * Enrol coursecompleted plugin + * + * @package enrol_coursecompleted + * @copyright 2017 eWallah (www.eWallah.net) + * @author Renaat Debleu + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class user_enrolment_callbacks { + + /** + * Callback for the user_enrolment hook. + * + * @param \core_enrol\hook\after_user_enrolled $hook + */ + public static function send_course_welcome_message(\core_enrol\hook\after_user_enrolled $hook): void { + global $CFG, $DB; + $instance = $hook->get_enrolinstance(); + // Send welcome message. + if ($instance->enrol == 'coursecompleted') { + if ($instance->customint2 > 0) { + $plugin = enrol_get_plugin($instance->enrol); + if ($complcourse = $DB->get_field('course', 'fullname', ['id' => $instance->customint1])) { + $context2 = context_course::instance($instance->customint1); + $a = new stdClass(); + $a->completed = format_string($complcourse, true, ['context' => $context2]); + $custom = $instance->customtext1; + if ($custom == '') { + $message = get_string('welcometocourse', 'enrol_coursecompleted', $a); + } else { + $key = ['{$a->completed}']; + $value = [$a->completed]; + $message = str_replace($key, $value, $custom); + } + $plugin->send_course_welcome_message_to_user( + instance: $instance, + userid: $hook->get_userid(), + sendoption: ENROL_SEND_EMAIL_FROM_NOREPLY, + message: $message, + ); + } + } + + // Keep the user in a group when needed. + if ($instance->customint3 > 0) { + require_once($CFG->dirroot . '/group/lib.php'); + $groups = array_values(groups_get_user_groups($instance->customint1, $hook->get_userid())); + foreach ($groups as $group) { + $subs = array_values($group); + foreach ($subs as $sub) { + $groupnamea = groups_get_group_name($sub); + $groupnameb = groups_get_group_by_name($instance->courseid, $groupnamea); + if ($groupnameb) { + groups_add_member($groupnameb, $hook->get_userid()); + } + } + } + } + } + } +} diff --git a/db/hooks.php b/db/hooks.php new file mode 100644 index 0000000..2757c90 --- /dev/null +++ b/db/hooks.php @@ -0,0 +1,33 @@ +. + +/** + * * Hook callbacks for enrol_coursecompleted. + * + * @package enrol_coursecompleted + * @copyright 2024 eWallah (www.eWallah.net) + * @author Renaat Debleu + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$callbacks = [ + [ + 'hook' => core_enrol\hook\after_user_enrolled::class, + 'callback' => 'enrol_coursecompleted\user_enrolment_callbacks::send_course_welcome_message', + ], +]; diff --git a/tests/backup_test.php b/tests/backup_test.php index 8428c61..4b586bd 100644 --- a/tests/backup_test.php +++ b/tests/backup_test.php @@ -83,7 +83,6 @@ public function test_backup_restore(): void { $ccompletion = new \completion_completion(['course' => $this->course1->id, 'userid' => $this->student->id]); $ccompletion->mark_complete(time()); - $this->runAdhocTasks(); $bc = new \backup_controller( \backup::TYPE_1COURSE, $this->course2->id, diff --git a/tests/behat/duration_enrolcoursecompleted.feature b/tests/behat/duration_enrolcoursecompleted.feature index d2038f3..37fdd07 100644 --- a/tests/behat/duration_enrolcoursecompleted.feature +++ b/tests/behat/duration_enrolcoursecompleted.feature @@ -55,7 +55,6 @@ Feature: Duration Enrolment on course completion When I follow "Click to mark user complete" And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks And I am on "Course 2" course homepage And I navigate to course participants Then I should see "2 participants found" diff --git a/tests/behat/enrol_coursecompleted.feature b/tests/behat/enrol_coursecompleted.feature index 8e9c253..c95e906 100644 --- a/tests/behat/enrol_coursecompleted.feature +++ b/tests/behat/enrol_coursecompleted.feature @@ -52,10 +52,8 @@ Feature: Enrolment on course completion And I click on "Course completion" "link" in the "region-main" "region" And I follow "Click to mark user complete" And I log out - And I log in as "admin" + And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks - And I log out When I am on the "C1" "Course" page logged in as "user1" Then I should not see "You will be enrolled in this course when" And I should see "Page A" @@ -81,7 +79,6 @@ Feature: Enrolment on course completion And I follow "Click to mark user complete" And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks And I am on "Course 2" course homepage Then I navigate to course participants # The user enrolment only starts in 2030 @@ -101,7 +98,6 @@ Feature: Enrolment on course completion And I follow "Click to mark user complete" And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks And I am on "Course 2" course homepage When I navigate to course participants # The user enrolment only starts in 2030 @@ -123,10 +119,8 @@ Feature: Enrolment on course completion And I click on "Course completion" "link" in the "region-main" "region" And I follow "Click to mark user complete" And I log out - And I log in as "admin" + And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks - And I log out And I am on the "C2" "Course" page logged in as "teacher1" And I navigate to course participants And I should see "Username 1" in the "participants" "table" @@ -162,9 +156,9 @@ Feature: Enrolment on course completion And I click on "Course completion" "link" in the "region-main" "region" And I follow "Click to mark user complete" And I log out - And I log in as "admin" + And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks + And I log in as "admin" And I am on "Course 2" course homepage And I navigate to course participants And I click on "Select all" "checkbox" @@ -184,10 +178,9 @@ Feature: Enrolment on course completion And I click on "Course completion" "link" in the "region-main" "region" And I follow "Click to mark user complete" And I log out - And I log in as "admin" + And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks - And I am on "Course 2" course homepage + And I am on the "C2" "Course" page logged in as "admin" And I navigate to course participants When I click on "Select 'Username 1'" "checkbox" And I set the field "With selected users..." to "Edit selected enrolments on course completion" diff --git a/tests/behat/enrol_groups.feature b/tests/behat/enrol_groups.feature index ce20f74..67db947 100644 --- a/tests/behat/enrol_groups.feature +++ b/tests/behat/enrol_groups.feature @@ -44,7 +44,6 @@ Feature: Groups kept during enrolment on course completion And I follow "Click to mark user complete" And I wait "1" seconds And I run the scheduled task "core\task\completion_regular_task" - And I run all adhoc tasks And I am on "Course 2" course homepage And I navigate to course participants diff --git a/tests/enrol_test.php b/tests/enrol_test.php index 85a1562..f897db6 100644 --- a/tests/enrol_test.php +++ b/tests/enrol_test.php @@ -103,6 +103,7 @@ protected function setUp(): void { /** * Test if user is enrolled after completing a course. * @covers \enrol_coursecompleted\observer + * @covers \enrol_coursecompleted\user_enrolment_callbacks */ public function test_event_enrolled(): void { global $PAGE; @@ -135,6 +136,7 @@ public function test_event_enrolled(): void { /** * Test if user is enrolled after completing a course. * @covers \enrol_coursecompleted_plugin + * @covers \enrol_coursecompleted\user_enrolment_callbacks */ public function test_enrolled_after_completion(): void { global $PAGE; @@ -146,7 +148,6 @@ public function test_enrolled_after_completion(): void { '100', \core_completion\progress::get_course_progress_percentage($this->course1, $this->student->id) ); - $this->runAdhocTasks(); $manager = new \course_enrolment_manager($PAGE, $this->course2); $this->assertCount(1, $manager->get_user_enrolments($this->student->id)); } @@ -163,7 +164,6 @@ public function test_user_edit(): void { '100', \core_completion\progress::get_course_progress_percentage($this->course1, $this->student->id) ); - $this->runAdhocTasks(); $this->setAdminUser(); $context = \context_course::instance($this->course1->id); $this->assertTrue(has_capability('report/completion:view', $context)); diff --git a/tests/other_test.php b/tests/other_test.php index 5684787..e7980f4 100644 --- a/tests/other_test.php +++ b/tests/other_test.php @@ -94,6 +94,7 @@ public function test_invalid_instance(): void { * Test disabled. * @covers \enrol_coursecompleted_plugin * @covers \enrol_coursecompleted\observer + * @covers \enrol_coursecompleted\user_enrolment_callbacks */ public function test_disabled(): void { global $CFG; @@ -161,6 +162,7 @@ public function test_static_past(): void { * Test invalid role. * @covers \enrol_coursecompleted_plugin * @covers \enrol_coursecompleted\observer + * @covers \enrol_coursecompleted\user_enrolment_callbacks */ public function test_invalid_role(): void { global $DB; @@ -190,6 +192,7 @@ public function test_invalid_role(): void { /** * Test group member. * @covers \enrol_coursecompleted\observer + * @covers \enrol_coursecompleted\user_enrolment_callbacks * @covers \enrol_coursecompleted_plugin */ public function test_groups_child(): void { @@ -231,6 +234,7 @@ public function test_groups_child(): void { $this->assertTrue(groups_is_member($groupid2, $studentid)); rebuild_course_cache($course1->id, true); rebuild_course_cache($course2->id, true); + // TODO: Why is hook not working? $this->assertTrue(groups_is_member($groupid1, $studentid)); } @@ -249,64 +253,40 @@ public function test_task(): void { } /** - * Test adhoc sending of welcome messages. - * @covers \enrol_coursecompleted\task\send_welcome + * Test welcome sending of welcome messages. + * @covers \enrol_coursecompleted\user_enrolment_callbacks */ - public function test_adhoc_email_welcome_message(): void { + public function test_email_welcome_message(): void { global $DB; $generator = $this->getDataGenerator(); - $sink = $this->redirectEmails(); + $messagesink = $this->redirectMessages(); $plugin = enrol_get_plugin('coursecompleted'); - $studentid = $generator->create_user()->id; - $course = $generator->create_course(['shortname' => 'B0', 'enablecompletion' => 1]); - $courseid1 = $generator->create_course(['shortname' => 'B1', 'enablecompletion' => 1])->id; - $courseid2 = $generator->create_course(['shortname' => 'B2', 'enablecompletion' => 1])->id; - $courseid3 = $generator->create_course(['shortname' => 'B3', 'enablecompletion' => 1])->id; - $courseid4 = $generator->create_course(['shortname' => 'B4', 'enablecompletion' => 1])->id; - $plugin->add_instance($course, ['customint1' => $courseid1, 'roleid' => 5, 'customint2' => 0]); - $i2 = $plugin->add_instance($course, ['customint1' => $courseid2, 'roleid' => 5, 'customint2' => 1]); - $i3 = $plugin->add_instance($course, ['customint1' => $courseid3, 'customtext1' => 'boe', 'customint2' => 1]); - $i4 = $plugin->add_instance( - $course, - ['customint1' => $courseid4, 'customtext1' => '{$a->fullname} boe -another line', 'customint2' => 1] - ); - $compevent = \core\event\course_completed::create( - [ - 'objectid' => $courseid1, - 'relateduserid' => $studentid, - 'context' => \context_course::instance($courseid1), - 'courseid' => $courseid1, - 'other' => ['relateduserid' => $studentid], - ] - ); - $observer = new observer(); - $observer->enroluser($compevent); - $adhock = new \enrol_coursecompleted\task\send_welcome(); - $adhock->set_custom_data( - ['userid' => $studentid, 'enrolid' => $i2, 'courseid' => $course->id, 'completedid' => $courseid2] - ); - $adhock->set_component('enrol_coursecompleted'); - $adhock->execute(); - \core\task\manager::queue_adhoc_task($adhock); - $adhock->set_custom_data( - ['userid' => $studentid, 'enrolid' => $i3, 'courseid' => $course->id, 'completedid' => $courseid3] - ); - \core\task\manager::queue_adhoc_task($adhock); - $adhock->set_custom_data( - ['userid' => $studentid, 'enrolid' => $i4, 'courseid' => $course->id, 'completedid' => $courseid4] + $student = $generator->create_user(); + $course1 = $generator->create_course(['shortname' => 'B1', 'enablecompletion' => 1]); + $course2 = $generator->create_course(['shortname' => 'B2', 'enablecompletion' => 1]); + $course3 = $generator->create_course(['shortname' => 'B3', 'enablecompletion' => 1]); + $plugin->add_instance($course1, ['customint1' => $course2->id, 'roleid' => 5, 'customint2' => 1, 'customtext1' => 'boe']); + $plugin->add_instance($course2, ['customint1' => $course3->id, 'roleid' => 5, 'customint2' => 1]); + $plugin->add_instance($course3, ['customint1' => $course1->id, 'roleid' => 5, 'customint2' => 1, 'customtext1' => ' +{$a->fullname} boe +another line'] ); - \core\task\manager::queue_adhoc_task($adhock); - $this->assertCount(3, $DB->get_records('task_adhoc', ['component' => 'enrol_coursecompleted'])); - \phpunit_util::run_all_adhoc_tasks(); - $messages = $sink->get_messages(); - $this->assertCount(4, $messages); - $sink->close(); - foreach ($messages as $message) { - $this->assertStringNotContainsString('{a->', $message->header); - $this->assertStringNotContainsString('{a->', $message->body); + $instances = $DB->get_records('enrol', ['enrol' => 'coursecompleted']); + foreach ($instances as $instance) { + $plugin->enrol_user($instance, $student->id); } - $this->assertCount(0, $DB->get_records('task_adhoc', ['component' => 'enrol_coursecompleted'])); + $messages = $messagesink->get_messages_by_component_and_type( + 'moodle', + 'enrolcoursewelcomemessage', + ); + $this->assertNotEmpty($messages); + $this->assertStringContainsString($course1->fullname, $messages[0]->subject); + $this->assertStringContainsString($course2->fullname, $messages[1]->subject); + $this->assertStringContainsString($course3->fullname, $messages[2]->subject); + $this->assertEquals('boe', $messages[0]->fullmessagehtml); + $this->assertStringContainsString($course3->fullname, $messages[1]->fullmessagehtml); + $this->assertStringContainsString(fullname($student), $messages[2]->fullmessagehtml); + $messagesink->close(); } /** diff --git a/version.php b/version.php index 2d36669..17d35fb 100644 --- a/version.php +++ b/version.php @@ -27,8 +27,9 @@ $plugin->component = 'enrol_coursecompleted'; -$plugin->requires = 2023042400; +$plugin->requires = 2024041600; $plugin->maturity = MATURITY_STABLE; -$plugin->supported = [402, 404]; -$plugin->release = 'v4.2.4'; -$plugin->version = 2024041900; +$plugin->supported = [404, 404]; +$plugin->release = 'v4.4.1'; +$plugin->version = 2024042900; +