From b6af21bec08b355aa8b4277977e951d048574ff4 Mon Sep 17 00:00:00 2001 From: Huong Nguyen Date: Tue, 16 Jan 2024 09:14:44 +0700 Subject: [PATCH] MDL-4188 enrol_manual: Send course welcome message on enrolment AMOS BEGIN CPY [customwelcomemessage,enrol_self],[customwelcomemessage,core_enrol] CPY [customwelcomemessage_help,enrol_self],[customwelcomemessage_help,core_enrol] AMOS END --- enrol/classes/hook/after_user_enrolled.php | 9 ++ .../classes/user_enrolment_callbacks.php | 46 ++++++ enrol/manual/db/hooks.php | 32 ++++ enrol/manual/lib.php | 67 ++++++++ enrol/manual/settings.php | 16 ++ .../manual/tests/behat/welcomemessage.feature | 123 ++++++++++++++ enrol/manual/tests/lib_test.php | 152 ++++++++++++++++++ enrol/manual/version.php | 2 +- enrol/self/lang/en/enrol_self.php | 17 +- lang/en/enrol.php | 13 ++ lang/en/moodle.php | 2 +- lib/enrollib.php | 99 +++++++++++- lib/upgrade.txt | 1 + 13 files changed, 568 insertions(+), 11 deletions(-) create mode 100644 enrol/manual/classes/user_enrolment_callbacks.php create mode 100644 enrol/manual/db/hooks.php create mode 100644 enrol/manual/tests/behat/welcomemessage.feature diff --git a/enrol/classes/hook/after_user_enrolled.php b/enrol/classes/hook/after_user_enrolled.php index 3d00294d310..9336f7793a9 100644 --- a/enrol/classes/hook/after_user_enrolled.php +++ b/enrol/classes/hook/after_user_enrolled.php @@ -49,4 +49,13 @@ class after_user_enrolled { public function get_userid(): int { return $this->userenrolmentinstance->userid; } + + /** + * Get the enrol instance. + * + * @return stdClass The enrol instance. + */ + public function get_enrolinstance(): stdClass { + return $this->enrolinstance; + } } diff --git a/enrol/manual/classes/user_enrolment_callbacks.php b/enrol/manual/classes/user_enrolment_callbacks.php new file mode 100644 index 00000000000..ac46dbb3388 --- /dev/null +++ b/enrol/manual/classes/user_enrolment_callbacks.php @@ -0,0 +1,46 @@ +. + +namespace enrol_manual; + +/** + * Hook callbacks to get the enrolment information. + * + * @package enrol_manual + * @copyright 2024 Huong Nguyen + * @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 { + $instance = $hook->get_enrolinstance(); + // Send welcome message. + if ($instance->enrol == 'manual' && $instance->customint1 && $instance->customint1 !== ENROL_DO_NOT_SEND_EMAIL) { + $plugin = enrol_get_plugin($instance->enrol); + $plugin->send_course_welcome_message_to_user( + instance: $instance, + userid: $hook->get_userid(), + sendoption: $instance->customint1, + message: $instance->customtext1, + ); + } + } +} diff --git a/enrol/manual/db/hooks.php b/enrol/manual/db/hooks.php new file mode 100644 index 00000000000..d1236526f0a --- /dev/null +++ b/enrol/manual/db/hooks.php @@ -0,0 +1,32 @@ +. + +/** + * Hook callbacks for enrol_manual + * + * @package enrol_manual + * @copyright 2024 Huong Nguyen + * @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_manual\user_enrolment_callbacks::send_course_welcome_message', + ], +]; diff --git a/enrol/manual/lib.php b/enrol/manual/lib.php index 89e935c366b..c41d5d970d0 100644 --- a/enrol/manual/lib.php +++ b/enrol/manual/lib.php @@ -135,6 +135,7 @@ class enrol_manual_plugin extends enrol_plugin { 'expirynotify' => $expirynotify, 'notifyall' => $expirynotify == 2 ? 1 : 0, 'expirythreshold' => $this->get_config('expirythreshold', 86400), + 'customint1' => $this->get_config('sendcoursewelcomemessage'), ); return $this->add_instance($course, $fields); } @@ -604,6 +605,62 @@ class enrol_manual_plugin extends enrol_plugin { $mform->addHelpButton('expirythreshold', 'expirythreshold', 'core_enrol'); $mform->disabledIf('expirythreshold', 'expirynotify', 'eq', 0); + // Course welcome message. + $mform->addElement( + 'select', + 'customint1', + get_string( + identifier: 'sendcoursewelcomemessage', + component: 'core_enrol', + ), + enrol_send_welcome_email_options(), + ); + $mform->addHelpButton( + elementname: 'customint1', + identifier: 'sendcoursewelcomemessage', + component: 'core_enrol', + ); + + $options = [ + 'cols' => '60', + 'rows' => '8', + ]; + $mform->addElement( + 'textarea', + 'customtext1', + get_string( + identifier: 'customwelcomemessage', + component: 'core_enrol', + ), + $options, + ); + $mform->setDefault('customtext1', get_string('customwelcomemessageplaceholder', 'core_enrol')); + $mform->hideIf( + elementname: 'customtext1', + dependenton: 'customint1', + condition: 'eq', + value: ENROL_DO_NOT_SEND_EMAIL, + ); + + // Static form elements cannot be hidden by hideIf() so we need to add a dummy group. + // See: https://tracker.moodle.org/browse/MDL-66251. + $group[] = $mform->createElement( + 'static', + 'customwelcomemessage_extra_help', + null, + get_string( + identifier: 'customwelcomemessage_help', + component: 'core_enrol', + ), + ); + $mform->addGroup($group, 'group_customwelcomemessage_extra_help', '', ' ', false); + $mform->hideIf( + elementname: 'group_customwelcomemessage_extra_help', + dependenton: 'customint1', + condition: 'eq', + value: ENROL_DO_NOT_SEND_EMAIL, + ); + if (enrol_accessing_via_instance($instance)) { $warntext = get_string('instanceeditselfwarningtext', 'core_enrol'); $mform->addElement('static', 'selfwarn', get_string('instanceeditselfwarning', 'core_enrol'), $warntext); @@ -689,6 +746,16 @@ class enrol_manual_plugin extends enrol_plugin { 'expirythreshold' => 0, ]; } + + /** + * Returns defaults for new instances. + * + * @return array + */ + public function get_instance_defaults(): array { + $fields['customint1'] = $this->get_config('sendcoursewelcomemessage'); + return $fields; + } } /** diff --git a/enrol/manual/settings.php b/enrol/manual/settings.php index 8dcabcc5951..9a79378c9bd 100644 --- a/enrol/manual/settings.php +++ b/enrol/manual/settings.php @@ -81,4 +81,20 @@ if ($ADMIN->fulltree) { $settings->add(new admin_setting_configduration('enrol_manual/expirythreshold', get_string('expirythreshold', 'core_enrol'), get_string('expirythreshold_help', 'core_enrol'), 86400, 86400)); + // Course welcome message. + $settings->add( + new admin_setting_configselect( + name: 'enrol_manual/sendcoursewelcomemessage', + visiblename: get_string( + identifier: 'sendcoursewelcomemessage', + component: 'core_enrol', + ), + description: get_string( + identifier: 'sendcoursewelcomemessage_help', + component: 'core_enrol', + ), + defaultsetting: ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, + choices: enrol_send_welcome_email_options(), + ), + ); } diff --git a/enrol/manual/tests/behat/welcomemessage.feature b/enrol/manual/tests/behat/welcomemessage.feature new file mode 100644 index 00000000000..17d5377d5c6 --- /dev/null +++ b/enrol/manual/tests/behat/welcomemessage.feature @@ -0,0 +1,123 @@ +@enrol @enrol_manual +Feature: A course welcome message will be sent to the user when they are enrolled in a course + In order to let the user know they have been enrolled in a course + As a teacher + I want the user to receive a welcome message when they are enrolled in a course + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | manager | Manager | User | manager@example.com | + | teacher | Teacher | User | teacher@example.com | + | user1 | First | User | first@example.com | + | user2 | Second | User | second@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + | Course 2 | C2 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | manager | C1 | manager | + | teacher | C1 | editingteacher | + | teacher | C2 | editingteacher | + + @javascript + Scenario: Manager should see the new settings for course welcome message + Given I am on the "C1" "Enrolled users" page logged in as manager + And I set the field "Participants tertiary navigation" to "Enrolment methods" + When I click on "Edit" "link" in the "Manual enrolments" "table_row" + Then I should see "Send course welcome message" + And the field "Send course welcome message" matches value "From the course contact" + And I should see "Custom welcome message" + And the field "Custom welcome message" matches value "Dear {$a->fullname}, you have successfully been enrolled to course {$a->coursename}" + And I should see "Accepted formats: Plain text or Moodle-auto format. HTML tags and multi-lang tags are also accepted, as well as the following placeholders:" + And I set the field "Send course welcome message" to "No" + And I should not see "Custom welcome message" + And I should not see "Accepted formats: Plain text or Moodle-auto format. HTML tags and multi-lang tags are also accepted, as well as the following placeholders:" + + @javascript + Scenario: Student should not receive a welcome message if the setting is disabled + Given I am on the "C1" "Enrolled users" page logged in as manager + And I set the field "Participants tertiary navigation" to "Enrolment methods" + And I click on "Edit" "link" in the "Manual enrolments" "table_row" + And I set the field "Send course welcome message" to "No" + And I press "Save changes" + And I am on the "C1" "Enrolled users" page logged in as teacher + And I press "Enrol users" + And I set the field "Select users" to "First User" + And I should see "First User" + And I click on "Enrol users" "button" in the "Enrol users" "dialogue" + And I should see "Active" in the "First User" "table_row" + When I am on the "C1" "course" page logged in as user1 + Then I should not see "1" in the "#nav-notification-popover-container [data-region='count-container']" "css_element" + + @javascript + Scenario: Students should receive a welcome message if the setting is enabled - Default message + Given I am on the "C1" "Enrolled users" page logged in as teacher + # Enrol first user to Course 1. + And I press "Enrol users" + And I set the field "Select users" to "First User" + And I should see "First User" + And I click on "Enrol users" "button" in the "Enrol users" "dialogue" + # Enrol second user to Course 2. + And I am on the "C2" "Enrolled users" page + And I press "Enrol users" + And I set the field "Select users" to "Second User" + And I should see "Second User" + And I click on "Enrol users" "button" in the "Enrol users" "dialogue" + # Login as first user and check the notification. + When I am on the "C1" "course" page logged in as user1 + Then I should see "1" in the "#nav-notification-popover-container [data-region='count-container']" "css_element" + And I open the notification popover + And I should see "Welcome to Course 1" + And I click on "View full notification" "link" in the ".popover-region-notifications" "css_element" + And I should see "Dear First User, you have successfully been enrolled to course Course 1" + # Login as second user and check the notification. + And I am on the "C1" "course" page logged in as user2 + And I should see "1" in the "#nav-notification-popover-container [data-region='count-container']" "css_element" + And I open the notification popover + And I should see "Welcome to Course 2" + And I click on "View full notification" "link" in the ".popover-region-notifications" "css_element" + And I should see "Dear Second User, you have successfully been enrolled to course Course 2" + + @javascript + Scenario: Students should receive a welcome message if the setting is enabled - Custom message + Given I am on the "C1" "Enrolled users" page logged in as manager + And I set the field "Participants tertiary navigation" to "Enrolment methods" + And I click on "Edit" "link" in the "Manual enrolments" "table_row" + And I set the field "Custom welcome message" to multiline: + """ + Dear {$a->fullname}, you have successfully been enrolled to course {$a->coursename}. + Your email address: {$a->email} + Your first name: {$a->firstname} + Your last name: {$a->lastname} + Your course role: {$a->courserole} + """ + And I press "Save changes" + # Enrol first user and second user to Course 1. + And the following "course enrolments" exist: + | user | course | role | + | user1 | C1 | student | + | user2 | C1 | student | + # Login as first user and check the notification. + When I am on the "C1" "course" page logged in as user1 + Then I should see "1" in the "#nav-notification-popover-container [data-region='count-container']" "css_element" + And I open the notification popover + And I should see "Welcome to Course 1" + And I click on "View full notification" "link" in the ".popover-region-notifications" "css_element" + And I should see "Dear First User, you have successfully been enrolled to course Course 1" + And I should see "Your email address: first@example.com" + And I should see "Your first name: First" + And I should see "Your last name: User" + And I should see "Your course role: student" + # Login as second user and check the notification. + When I am on the "C1" "course" page logged in as user2 + Then I should see "1" in the "#nav-notification-popover-container [data-region='count-container']" "css_element" + And I open the notification popover + And I should see "Welcome to Course 1" + And I click on "View full notification" "link" in the ".popover-region-notifications" "css_element" + And I should see "Dear Second User, you have successfully been enrolled to course Course 1" + And I should see "Your email address: second@example.com" + And I should see "Your first name: Second" + And I should see "Your last name: User" + And I should see "Your course role: student" diff --git a/enrol/manual/tests/lib_test.php b/enrol/manual/tests/lib_test.php index ce51f186a7d..28258e8d7f8 100644 --- a/enrol/manual/tests/lib_test.php +++ b/enrol/manual/tests/lib_test.php @@ -789,4 +789,156 @@ class lib_test extends \advanced_testcase { $this->assertEquals($expected->id, $actual->id); } + /** + * Test send_course_welcome_message_to_user() method. + * + * @covers \enrol_plugin::send_course_welcome_message_to_user + */ + public function test_send_course_welcome_message(): void { + global $DB; + $this->resetAfterTest(); + + // Create course. + $course = $this->getDataGenerator()->create_course([ + 'fullname' => 'Course 1', + 'shortname' => 'C1', + ]); + // Create users. + $student = $this->getDataGenerator()->create_user(); + $teacher1 = $this->getDataGenerator()->create_user(); + $teacher2 = $this->getDataGenerator()->create_user(); + $noreplyuser = \core_user::get_noreply_user(); + // Enrol users. + $this->getDataGenerator()->enrol_user($teacher1->id, $course->id, 'editingteacher'); + $this->getDataGenerator()->enrol_user($teacher2->id, $course->id, 'editingteacher'); + // Get manual plugin. + $manualplugin = enrol_get_plugin('manual'); + $maninstance = $DB->get_record( + 'enrol', + ['courseid' => $course->id, 'enrol' => 'manual'], + '*', + MUST_EXIST, + ); + + // Test 1: Send welcome message to user from course contact with default message. + // Redirect messages. + $messagesink = $this->redirectMessages(); + $manualplugin->send_course_welcome_message_to_user( + instance: $maninstance, + userid: $student->id, + sendoption: ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, + message: '', + ); + $messages = $messagesink->get_messages_by_component_and_type( + 'moodle', + 'enrolcoursewelcomemessage', + ); + $this->assertNotEmpty($messages); + $message = reset($messages); + + // The message should be sent from the first teacher. + $this->assertEquals($teacher1->id, $message->useridfrom); + $this->assertStringContainsString($course->fullname, $message->subject); + $this->assertEquals( + get_string( + 'customwelcomemessageplaceholder', + 'core_enrol', + ['fullname' => fullname($student), 'coursename' => $course->fullname], + ), + $message->fullmessage, + ); + + // Clear sink. + $messagesink->clear(); + + // Test 2: Send welcome message to user from course contact with a custom message. + // Unenrol the first teacher from course. + $manualplugin->unenrol_user($maninstance, $teacher1->id); + // Redirect messages. + $messagesink = $this->redirectMessages(); + $manualplugin->send_course_welcome_message_to_user( + instance: $maninstance, + userid: $student->id, + sendoption: ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, + message: 'Your email address: {$a->email}, your first name: {$a->firstname}, your last name: {$a->lastname}', + ); + $messages = $messagesink->get_messages_by_component_and_type( + 'moodle', + 'enrolcoursewelcomemessage', + ); + $this->assertNotEmpty($messages); + $message = reset($messages); + + // The message should be sent from the second teacher. + $this->assertEquals($teacher2->id, $message->useridfrom); + $this->assertStringContainsString($course->fullname, $message->subject); + $this->assertEquals( + 'Your email address: ' . $student->email . ', your first name: ' . $student->firstname . ', your last name: ' . + $student->lastname, + $message->fullmessage, + ); + // Clear sink. + $messagesink->clear(); + + // Test 3: Send welcome message to user from no-reply user with a custom message. + // Redirect messages. + $messagesink = $this->redirectMessages(); + $manualplugin->send_course_welcome_message_to_user( + instance: $maninstance, + userid: $student->id, + sendoption: ENROL_SEND_EMAIL_FROM_NOREPLY, + message: 'Your email address: {$a->email}, your first name: {$a->firstname}, your last name: {$a->lastname}', + ); + $messages = $messagesink->get_messages_by_component_and_type( + 'moodle', + 'enrolcoursewelcomemessage', + ); + $this->assertNotEmpty($messages); + $message = reset($messages); + + // The message should be sent from the noreply user. + $this->assertEquals($noreplyuser->id, $message->useridfrom); + $this->assertStringContainsString($course->fullname, $message->subject); + $this->assertEquals( + 'Your email address: ' . $student->email . ', your first name: ' . $student->firstname . ', your last name: ' . + $student->lastname, + $message->fullmessage, + ); + // Clear sink. + $messagesink->clear(); + + } + + /** + * Test send_course_welcome_message_to_user() method via hook. + * + * @covers \enrol_plugin::send_course_welcome_message_to_user + */ + public function test_send_course_welcome_message_via_hook(): void { + global $DB; + $this->resetAfterTest(); + $messagesink = $this->redirectMessages(); + $course = $this->getDataGenerator()->create_course([ + 'fullname' => 'Course 1', + 'shortname' => 'C1', + ]); + $maninstance = $DB->get_record( + 'enrol', + ['courseid' => $course->id, 'enrol' => 'manual'], + '*', + MUST_EXIST, + ); + $maninstance->customint1 = ENROL_SEND_EMAIL_FROM_NOREPLY; + $DB->update_record('enrol', $maninstance); + $student = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($student->id, $course->id); + $messages = $messagesink->get_messages_by_component_and_type( + 'moodle', + 'enrolcoursewelcomemessage', + ); + $this->assertNotEmpty($messages); + $message = reset($messages); + $this->assertStringContainsString($course->fullname, $message->subject); + } + } diff --git a/enrol/manual/version.php b/enrol/manual/version.php index 5516803a188..fec37be7983 100644 --- a/enrol/manual/version.php +++ b/enrol/manual/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023100900; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2023100901; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2023100400; // Requires this Moodle version. $plugin->component = 'enrol_manual'; // Full name of the plugin (used for diagnostics) diff --git a/enrol/self/lang/en/enrol_self.php b/enrol/self/lang/en/enrol_self.php index 39128095ec7..c5c0afa10f6 100644 --- a/enrol/self/lang/en/enrol_self.php +++ b/enrol/self/lang/en/enrol_self.php @@ -30,14 +30,15 @@ $string['cohortonly'] = 'Only cohort members'; $string['cohortonly_help'] = 'Self enrolment may be restricted to members of a specified cohort only. Note that changing this setting has no effect on existing enrolments.'; $string['confirmbulkdeleteenrolment'] = 'Are you sure you want to delete these user enrolments?'; $string['customwelcomemessage'] = 'Custom welcome message'; -$string['customwelcomemessage_help'] = 'A custom welcome message may be added as plain text or Moodle-auto format, including HTML tags and multi-lang tags. - -The following placeholders may be included in the message: - -* Course name {$a->coursename} -* Link to user\'s profile page {$a->profileurl} -* User email {$a->email} -* User fullname {$a->fullname}'; +$string['customwelcomemessage_help'] = 'Accepted formats: Plain text or Moodle-auto format. HTML tags and multi-lang tags are also accepted, as well as the following placeholders: +
+* Course name {$a->coursename}
+* Link to user\'s profile page {$a->profileurl}
+* User email {$a->email}
+* User fullname {$a->fullname}
+* User first name {$a->firstname}
+* User last name {$a->lastname}
+* User course role {$a->courserole}
'; $string['defaultrole'] = 'Default role assignment'; $string['defaultrole_desc'] = 'Select role which should be assigned to users during self enrolment'; $string['deleteselectedusers'] = 'Delete selected user enrolments'; diff --git a/lang/en/enrol.php b/lang/en/enrol.php index 014e59d32c4..7d6ad4b494c 100644 --- a/lang/en/enrol.php +++ b/lang/en/enrol.php @@ -34,6 +34,17 @@ $string['assignnotpermitted'] = 'You do not have permission or can not assign ro $string['bulkuseroperation'] = 'Bulk user operation'; $string['configenrolplugins'] = 'Please select all required plugins and arrange then in appropriate order.'; $string['custominstancename'] = 'Custom instance name'; +$string['customwelcomemessage'] = 'Custom welcome message'; +$string['customwelcomemessage_help'] = 'Accepted formats: Plain text or Moodle-auto format. HTML tags and multi-lang tags are also accepted, as well as the following placeholders: +
+* Course name {$a->coursename}
+* Link to user\'s profile page {$a->profileurl}
+* User email {$a->email}
+* User fullname {$a->fullname}
+* User first name {$a->firstname}
+* User last name {$a->lastname}
+* User course role {$a->courserole}
'; +$string['customwelcomemessageplaceholder'] = 'Dear {$a->fullname}, you have successfully been enrolled to course {$a->coursename}'; $string['defaultenrol'] = 'Add instance to new courses'; $string['defaultenrol_desc'] = 'It is possible to add this plugin to all new courses by default.'; $string['deleteinstanceconfirm'] = 'You are about to delete the enrolment method "{$a->name}". All {$a->users} users currently enrolled using this method will be unenrolled and any course-related data such as users\' grades, group membership or forum subscriptions will be deleted. @@ -129,6 +140,8 @@ $string['rolefromsystem'] = '{$a->role} (Assigned at site level)'; $string['sendfromcoursecontact'] = 'From the course contact'; $string['sendfromkeyholder'] = 'From the key holder'; $string['sendfromnoreply'] = 'From the no-reply address'; +$string['sendcoursewelcomemessage'] = 'Send course welcome message'; +$string['sendcoursewelcomemessage_help'] = 'When enrolling a user or cohort in the course, they may be sent a welcome message email. If sent from the course contact (by default the teacher), and more than one user has this role, the email is sent from the first user to be assigned the role.'; $string['startdatetoday'] = 'Today'; $string['synced'] = 'Synced'; $string['testsettings'] = 'Test settings'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index e2fd3c4f54d..8b89877de87 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -2404,7 +2404,7 @@ $string['welcometocoursetext'] = 'Welcome to {$a->coursename}! If you have not done so already, you should edit your profile page so that we can learn more about you: - {$a->profileurl}'; +{$a->profileurl}'; $string['whatforlink'] = 'What do you want to do with the link?'; $string['whatforpage'] = 'What do you want to do with the text?'; $string['whatisyourage'] = 'What is your age?'; diff --git a/lib/enrollib.php b/lib/enrollib.php index 61e0f5119d2..cd2c2f77c54 100644 --- a/lib/enrollib.php +++ b/lib/enrollib.php @@ -3610,7 +3610,7 @@ abstract class enrol_plugin { $userfieldsapi = \core_user\fields::for_name(); $allnames = $userfieldsapi->get_sql('u', false, '', '', false)->selects; $rusers = get_role_users($croles[$i], $context, true, 'u.id, u.confirmed, u.username, '. $allnames . ', - u.email, r.sortorder, ra.id', 'r.sortorder, ra.id ASC, ' . $sort, null, '', '', '', '', $sortparams); + u.email, r.sortorder, ra.id AS raid', 'r.sortorder, ra.id ASC, ' . $sort, null, '', '', '', '', $sortparams); $i++; } while (empty($rusers) && !empty($croles[$i])); } @@ -3632,4 +3632,101 @@ abstract class enrol_plugin { return $contact; } + + /** + * Send course welcome message to user. + * + * @param stdClass $instance Enrol instance. + * @param int $userid User ID. + * @param int $sendoption Send email from constant ENROL_SEND_EMAIL_FROM_* + * @param null|string $message Message to send to the user. + */ + public function send_course_welcome_message_to_user( + stdClass $instance, + int $userid, + int $sendoption, + ?string $message = '', + ): void { + global $DB; + $context = context_course::instance($instance->courseid); + $user = core_user::get_user($userid); + $course = get_course($instance->courseid); + $courserole = $DB->get_field( + table: 'role', + return: 'shortname', + conditions: ['id' => $instance->roleid], + ); + + $a = new stdClass(); + $a->coursename = format_string($course->fullname, true, ['context' => $context]); + $a->profileurl = (new moodle_url( + url: '/user/view.php', + params: [ + 'id' => $user->id, + 'course' => $instance->courseid, + ], + ))->out(); + $a->fullname = fullname($user); + + if ($message && trim($message) !== '') { + $placeholders = [ + '{$a->coursename}', + '{$a->profileurl}', + '{$a->fullname}', + '{$a->email}', + '{$a->firstname}', + '{$a->lastname}', + '{$a->courserole}', + ]; + $values = [ + $a->coursename, + $a->profileurl, + fullname($user), + $user->email, + $user->firstname, + $user->lastname, + $courserole, + ]; + $message = str_replace($placeholders, $values, $message); + if (strpos($message, '<') === false) { + // Plain text only. + $messagetext = $message; + $messagehtml = text_to_html($messagetext, null, false, true); + } 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]); + $messagetext = html_to_text($messagehtml); + } + } else { + $messagetext = get_string('customwelcomemessageplaceholder', 'core_enrol', $a); + $messagehtml = text_to_html($messagetext, null, false, true); + } + + $subject = get_string('welcometocourse', 'moodle', format_string($course->fullname, true, ['context' => $context])); + $contact = $this->get_welcome_message_contact( + sendoption: $sendoption, + context: $context, + ); + if (!$contact) { + // Cannot find the contact to send the message from. + return; + } + + $message = new \core\message\message(); + $message->courseid = $instance->courseid; + $message->component = 'moodle'; + $message->name = 'enrolcoursewelcomemessage'; + $message->userfrom = $contact; + $message->userto = $user; + $message->subject = $subject; + $message->fullmessage = $messagetext; + $message->fullmessageformat = FORMAT_MARKDOWN; + $message->fullmessagehtml = $messagehtml; + $message->notification = 1; + $message->contexturl = $a->profileurl; + $message->contexturlname = $course->fullname; + + message_send($message); + } } diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 68adac414c7..0691cbe6d95 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -138,6 +138,7 @@ information provided here is intended especially for developers. - Deprecation: Cannot use the "Test" suffix on abstract test case classes. Proceed to rename them to end with "TestCase" instead. * There is a new method called enrol_plugin::get_welcome_message_contact() that returns the contact details for the course welcome message. +* There is a new method called enrol_plugin::send_course_welcome_message_to_user() that sends the course welcome message to a user. === 4.3 ===