diff --git a/classes/bulkenrol_form.php b/classes/bulkenrol_form.php index c0169a4..7266aba 100644 --- a/classes/bulkenrol_form.php +++ b/classes/bulkenrol_form.php @@ -50,15 +50,51 @@ protected function definition() { $mform = $this->_form; + // Selector for database field to match list to. + $availablefieldsstring = get_config('local_bulkenrol', 'fieldoptions'); + $availablefieldsarray = explode(',', $availablefieldsstring); + if (count($availablefieldsarray) < 1 or $availablefieldsarray[0] == '') { + print_error(get_string('error_no_options_available', 'local_bulkenrol')); + } + + $selectoptions = []; + foreach ($availablefieldsarray as $fieldoption) { + $selectoptions[$fieldoption] = $this->get_fieldname($fieldoption); + } + + // Format CSV, replace last , with 'or' and add spaces after remaining. + $fieldnamestring = implode(', ', $selectoptions); + $formattedfieldnamestring = $this->str_last_replace(', ', ' ' . get_string('or', 'local_bulkenrol') . ' ', $fieldnamestring); + // Infotext. - $msg = get_string('bulkenrol_form_intro', 'local_bulkenrol'); + $msg = get_string('bulkenrol_form_intro', 'local_bulkenrol', $formattedfieldnamestring); $mform->addElement('html', '
'.$msg.'
'); - // Textarea for Emails. - $mform->addElement('textarea', 'usermails', - get_string('usermails', 'local_bulkenrol'), 'wrap="virtual" rows="10" cols="80"'); - $mform->addRule('usermails', null, 'required'); - $mform->addHelpButton('usermails', 'usermails', 'local_bulkenrol'); + // Helptext. + if ($availablefieldsarray[0] == 'u_username') { + $helpstringidentifier = 'userlist_username'; + } else if ($availablefieldsarray[0] == 'u_idnumber') { + $helpstringidentifier = 'userlist_idnumber'; + } else { + $helpstringidentifier = 'userlist_email'; + } + + $singleoption = count($availablefieldsarray) == 1; + if (!$singleoption) { + $mform->addElement('select', 'dbfield', get_string('choose_field', 'local_bulkenrol'), $selectoptions); + $listfieldtitle = get_string('userlist', 'local_bulkenrol'); + } else { + $field = $availablefieldsarray[0]; + $mform->addElement('hidden', 'dbfield'); + $mform->setType('dbfield', PARAM_TEXT); + $mform->setDefault('dbfield', $field); + $listfieldtitle = get_string('userlist_singleoption', 'local_bulkenrol', $this->get_fieldname($field)); + } + // Textarea for uservalues. + $mform->addElement('textarea', 'uservalues', + $listfieldtitle, 'wrap="virtual" rows="10" cols="80"'); + $mform->addRule('uservalues', null, 'required'); + $mform->addHelpButton('uservalues', $helpstringidentifier, 'local_bulkenrol'); // Add form content if the user came back to check his input. $localbulkenroleditlist = optional_param('editlist', 0, PARAM_ALPHANUMEXT); @@ -66,8 +102,10 @@ protected function definition() { $localbulkenroldata = $localbulkenroleditlist.'_data'; if (!empty($localbulkenroldata) && !empty($SESSION->local_bulkenrol_inputs) && array_key_exists($localbulkenroldata, $SESSION->local_bulkenrol_inputs)) { - $formdatatmp = $SESSION->local_bulkenrol_inputs[$localbulkenroldata]; - $mform->setDefault('usermails', $formdatatmp); + $formdatatmp = $SESSION->local_bulkenrol_inputs[$localbulkenroldata]['users']; + $dbfield = $SESSION->local_bulkenrol_inputs[$localbulkenroldata]['dbfield']; + $mform->setDefault('uservalues', $formdatatmp); + $mform->setDefault('dbfield', $dbfield); } } @@ -89,10 +127,47 @@ protected function definition() { public function validation($data, $files) { $retval = array(); - if (empty($data['usermails'])) { - $retval['usermails'] = get_string('error_usermails_empty', 'local_bulkenrol'); + if (empty($data['uservalues'])) { + $retval['uservalues'] = get_string('error_list_empty', 'local_bulkenrol'); } return $retval; } + + /** + * Returns the name of a fieldoption without its table prefix + * @param string $fieldoption fieldname with type prefix + * @return string name of field without type prefix + * @throws \UnexpectedValueException Field is not prefixed by c_ or u_ + * @throws \dml_exception Database connection error + */ + private function get_fieldname($fieldoption) { + global $DB; + $fieldinfo = explode("_", $fieldoption, 2); + switch ($fieldinfo[0]) { + case "u": + return $fieldinfo[1]; + case "c": + return $DB->get_field('user_info_field', 'name', array("id" => intval($fieldinfo[1]))); + default: + throw new \UnexpectedValueException("field is not from usertable (u_) or customfield (c_)"); + } + } + + /** + * Replaces the last occurence of the needle in a string. + * @param string $search needle to search for + * @param string $replace string replacement for needle + * @param string $subject string subject string to search + * @return string subject string with the last occurence of the needle replaced + */ + private function str_last_replace($search, $replace, $subject) { + $pos = strrpos($subject, $search); + + if ($pos !== false) { + $subject = substr_replace($subject, $replace, $pos, strlen($search)); + } + + return $subject; + } } diff --git a/index.php b/index.php index 2e12cc6..8e6a6b0 100644 --- a/index.php +++ b/index.php @@ -59,10 +59,17 @@ if (empty($localbulkenrolkey)) { $form = new bulkenrol_form(null, array('courseid' => $id)); if ($formdata = $form->get_data()) { - $emails = $formdata->usermails; + $datafield = $formdata->dbfield; + $uservalues = $formdata->uservalues; $courseid = $formdata->id; - $checkedmails = local_bulkenrol_check_user_mails($emails, $courseid); + $availablefieldsstring = get_config('local_bulkenrol', 'fieldoptions'); + $availablefieldsarray = explode(',', $availablefieldsstring); + if (!in_array($datafield, $availablefieldsarray)) { + print_error('The provided datafield has not been approved by the administrator.', 'local_bulkenrol'); + } + + $checkedusers = local_bulkenrol_check_user_data($uservalues, $courseid, $datafield); // Create local_bulkenrol array in Session. if (!isset($SESSION->local_bulkenrol)) { @@ -70,14 +77,14 @@ } // Save data in Session. $localbulkenrolkey = $courseid.'_'.time(); - $SESSION->local_bulkenrol[$localbulkenrolkey] = $checkedmails; + $SESSION->local_bulkenrol[$localbulkenrolkey] = $checkedusers; // Create local_bulkenrol_inputs array in session. if (!isset($SESSION->local_bulkenrol_inputs)) { $SESSION->local_bulkenrol_inputs = array(); } $localbulkenroldata = $localbulkenrolkey.'_data'; - $SESSION->local_bulkenrol_inputs[$localbulkenroldata] = $emails; + $SESSION->local_bulkenrol_inputs[$localbulkenroldata] = array('users' => $uservalues, 'dbfield' => $datafield); } else if ($form->is_cancelled()) { if (!empty($id)) { redirect($CFG->wwwroot .'/course/view.php?id='.$id, '', 0); @@ -130,13 +137,13 @@ } // Show notification if there aren't any valid email addresses to enrol. - if (!empty($localbulkenroldata) && isset($localbulkenroldata->validemailfound) && - empty($localbulkenroldata->validemailfound)) { + if (!empty($localbulkenroldata) && isset($localbulkenroldata->validusersfound) && + empty($localbulkenroldata->validusersfound)) { $a = new stdClass(); $url = new moodle_url('/local/bulkenrol/index.php', array('id' => $id, 'editlist' => $localbulkenrolkey)); $a->url = $url->out(); $notification = new \core\output\notification( - get_string('error_no_valid_email_in_list', 'local_bulkenrol', $a), + get_string('error_no_valid_data_in_list', 'local_bulkenrol', $a), \core\output\notification::NOTIFY_WARNING); $notification->set_show_closebutton(false); echo $OUTPUT->render($notification); diff --git a/lang/en/local_bulkenrol.php b/lang/en/local_bulkenrol.php index 4f00c4a..c161904 100644 --- a/lang/en/local_bulkenrol.php +++ b/lang/en/local_bulkenrol.php @@ -25,39 +25,49 @@ defined('MOODLE_INTERNAL') || die(); $string['bulkenrol:enrolusers'] = 'Use user bulk enrolment'; -$string['bulkenrol_form_intro'] = 'Here, you can bulk enrol users to your course. A user to be enrolled is identified by his e-mail address stored in his Moodle account.'; +$string['bulkenrol_form_intro'] = 'Here, you can bulk enrol users to your course. A user to be enrolled is identified by their {$a}.'; +$string['choose_field'] = 'Choose field to match list to'; $string['enrol_users_successful'] = 'User bulk enrolment successful'; $string['enrol_users'] = 'Enrol users'; $string['enrolinfo_headline'] = 'Enrolment details'; $string['enrolplugin'] = 'Enrolment plugin'; $string['enrolplugin_desc'] = 'The enrolment method to be used to bulk enrol the users. If the configured enrolment method is not active / added in the course when the users are bulk-enrolled, it is automatically added / activated.'; $string['error_enrol_users'] = 'There was a problem when enrolling the users to the course.'; -$string['error_enrol_user'] = 'There was a problem when enrolling the user with e-mail {$a->email} to the course.'; +$string['error_enrol_user'] = 'There was a problem when enrolling the user {$a->data} to the course.'; $string['error_exception_info'] = 'Exception information'; -$string['error_getting_user_for_email'] = 'There was a problem when getting the user record for e-mail address {$a} from the database.'; +$string['error_getting_user_for_data'] = 'There was a problem when getting the user record for {$a} from the database.'; $string['error_group_add_members'] = 'There was a problem when adding the users to the course group(s).'; -$string['error_group_add_member'] = 'There was a problem when adding the user with e-mail {$a->email} to the course group {$a->group}.'; -$string['error_invalid_email'] = 'Invalid e-mail address found in line {$a->row} ({$a->email}). This line will be ignored.'; -$string['error_more_than_one_record_for_email'] = 'More than one existing Moodle user account with e-mail address {$a}em> found.
This line will be ignored, none of the existing Moodle users will be enrolled.'; -$string['error_no_email'] = 'No e-mail address found in line {$a->line} ({$a->content}). This line will be ignored.'; -$string['error_no_valid_email_in_list'] = 'No valid e-mail address was found in the given list.
Please url}\'>go back and check your input.'; -$string['error_no_record_found_for_email'] = 'No existing Moodle user account with e-mail address {$a}.
This line will be ignored, there won\'t be a Moodle user account created on-the-fly.'; -$string['error_usermails_empty'] = 'List of e-mail addresses is empty. Please add at least one e-mail address.'; -$string['error_check_is_already_member'] = 'Error checking if the user ({$a->email}) is already a member of group ({$a->groupname}). {$a->error}'; +$string['error_group_add_member'] = 'There was a problem when adding the user {$a->data} to the course group {$a->group}.'; +$string['error_more_than_one_record_for_data'] = 'More than one existing Moodle user account with {$a->field} {$a->identifier}em> found.
This line will be ignored, none of the existing Moodle users will be enrolled.'; +$string['error_no_valid_data_in_list'] = 'No valid entrys were found in the given list.
Please url}\'>go back and check your input.'; $string['groupinfos_headline'] = 'Groups included in the list'; $string['group_name_headline'] = 'Group name'; $string['group_status_create'] = 'Group will be created'; $string['group_status_exists'] = 'Group already exists'; $string['group_status_headline'] = 'Group status'; $string['hints'] = 'Hints'; +$string['error_no_data'] = 'No data found ({$a}). This line will be ignored.'; +$string['error_no_record_found_for_data'] = 'No existing Moodle user account {$a} was found.
This line will be ignored, there won\'t be a Moodle user account created on-the-fly.'; +$string['error_no_options_available'] = 'Your administrator has disabled all options. Please contact your administrator'; +$string['error_list_empty'] = 'List is empty. Please add at least one fieldvalue'; +$string['error_check_is_already_member'] = 'Error checking if the user ({$a->data}) is already a member of group ({$a->groupname}). {$a->error}'; +$string['fieldoptions'] = 'Fieldoptions'; +$string['fieldoptions_desc'] = 'Fields, that teachers can use as identifier to enrol students by.'; $string['pluginname'] = 'User bulk enrolment'; +$string['or'] = 'or'; $string['privacy:metadata'] = 'The user bulk enrolment plugin acts as a tool to enrol users into courses, but does not store any personal data.'; $string['role'] = 'Role'; $string['role_assigned'] = 'Assigned role'; $string['role_description'] = 'The role to be used to bulk enrol the users.'; $string['row'] = 'Row'; -$string['usermails'] = 'List of e-mail addresses'; -$string['usermails_help'] = 'To enrol an existing Moodle user into this course, add his e-mail address to this form, one user / e-mail address per line.

Example:
alice@example.com
bob@example.com

Optionally, you are able to create groups and add the enrolled users to the groups. All you have to do is to add a heading line with a hash sign and the group\'s name, separating the list of users.

Example:
# Group 1
alice@example.com
bob@example.com
# Group 2
carol@example.com
dave@example.com'; +$string['userlist'] = 'List of users identified by your chosen field'; +$string['userlist_singleoption'] = 'List of users identified by their {$a}'; +$string['userlist_email'] = 'data input'; +$string['userlist_username'] = 'data input'; +$string['userlist_idnumber'] = 'data input'; +$string['userlist_email_help'] = 'To enrol an existing Moodle user into this course, choose a field to identify the user by and add the identifier to the list.

Example for field "email" :
alice@example.com
bob@example.com

Optionally, you are able to create groups and add the enrolled users to the groups. All you have to do is to add a heading line with a hash sign and the group\'s name, separating the list of users.

Example:
# Group 1
alice@example.com
bob@example.com
# Group 2
carol@example.com
dave@example.com'; +$string['userlist_username_help'] = 'To enrol an existing Moodle user into this course, choose a field to identify the user by and add the identifier to the list.

Example for field "username" :
alice
bob

Optionally, you are able to create groups and add the enrolled users to the groups. All you have to do is to add a heading line with a hash sign and the group\'s name, separating the list of users.

Example:
# Group 1
alice
bob
# Group 2
carol
dave'; +$string['userlist_idnumber_help'] = 'To enrol an existing Moodle user into this course, choose a field to identify the user by and add the identifier to the list.

Example for field "idnumber" :
1001
1002

Optionally, you are able to create groups and add the enrolled users to the groups. All you have to do is to add a heading line with a hash sign and the group\'s name, separating the list of users.

Example:
# Group 1
1001
1002
# Group 2
1003
1004'; $string['users_to_enrol_in_course'] = 'Users to be enrolled into the course'; $string['user_enroled'] = 'User enrolment'; $string['user_enroled_yes'] = 'User will be enrolled'; @@ -67,3 +77,5 @@ $string['user_groups_already'] = 'User is already group member'; $string['parameter_empty'] = 'Parameter empty'; $string['type_enrol'] = 'Enrolment method'; +$string['identifying_data'] = 'Data'; + diff --git a/locallib.php b/locallib.php index 3036381..297fa47 100644 --- a/locallib.php +++ b/locallib.php @@ -29,205 +29,175 @@ define('LOCALBULKENROL_GROUPINFOS', 'groupinfos'); /** - * Check list of submitted user mails and creates a data structure for displaying information on the confirm page and + * Check list of submitted user data and creates a data structure for displaying information on the confirm page and * for performing the bulkenrol. * - * @param string $emailstextfield Text field value to be checked for emails and course groups. + * @param string $userdatatext Text field value to be checked for identifying data and course groups. * @param int $courseid ID of the course, used to determine the context for checking whether a user is already enroled. + * @param string $datafield To which database field to compare the user data. + * u_* for Fields of the user-table, c_* for custom fields. * * @return stdClass Object containing information to be displayed on confirm page and being used for bulkenrol. */ -function local_bulkenrol_check_user_mails($emailstextfield, $courseid) { +function local_bulkenrol_check_user_data($userdatatext, $courseid, $datafield = 'u_email') { - $checkedemails = new stdClass(); - $checkedemails->emails_to_ignore = array(); - $checkedemails->error_messages = array(); - $checkedemails->moodleusers_for_email = array(); - $checkedemails->course_groups = array(); - $checkedemails->user_groups = array(); - $checkedemails->user_enroled = array(); - $checkedemails->validemailfound = 0; + $checkeddata = new stdClass(); + $checkeddata->data_to_ignore = array(); + $checkeddata->error_messages = array(); + $checkeddata->moodleusers_for_data = array(); + $checkeddata->course_groups = array(); + $checkeddata->user_groups = array(); + $checkeddata->user_enroled = array(); + $checkeddata->validusersfound = 0; - $emaildelimiters = array(', ', ' ', ','); + $possibledelimiters = array(', ', ' ', ','); - if (!empty($emailstextfield)) { - - $emailslines = local_bulkenrol_parse_emails($emailstextfield); + if (empty($userdatatext)) { + return $checkeddata; + } - $linecnt = 0; + $datafieldsstring = get_config('local_bulkenrol', 'fieldoptions'); + $datafields = explode(",", $datafieldsstring); + if (!is_array($datafields) || !in_array($datafield, $datafields)) { + return $checkeddata; + } - $currentgroup = ''; + $datalines = local_bulkenrol_parse_data($userdatatext); - $context = null; + $linecnt = 0; - if (!empty($courseid)) { - $context = context_course::instance($courseid, MUST_EXIST); - } + $currentgroup = ''; - // Process emails from textfield. - foreach ($emailslines as $emailline) { - $linecnt++; + $context = null; - $error = ''; + if (!empty($courseid)) { + $context = context_course::instance($courseid, MUST_EXIST); + } - $emailline = trim($emailline); + // Process data from textfield. + foreach ($datalines as $dataline) { + $linecnt++; - // Check for course group. - $grouppos = strpos($emailline , '#'); - if ($grouppos !== false) { + $error = ''; - $groupname = substr($emailline, $grouppos + 1); - $currentgroup = trim($groupname); - $checkedemails->course_groups[$currentgroup] = array(); - continue; - } + $dataline = trim($dataline); - // Check number of emails in current row/line. - $emailsinlinecnt = substr_count($emailline , '@'); + // Check for course group. + $grouppos = strpos($dataline, '#'); + if ($grouppos !== false) { - // No email in row/line. - if ($emailsinlinecnt == 0) { + $groupname = substr($dataline, $grouppos + 1); + $currentgroup = trim($groupname); + $checkeddata->course_groups[$currentgroup] = array(); + continue; + } - $a = new stdClass(); - $a->line = $linecnt; - $a->content = $emailline; - $error = get_string('error_no_email', 'local_bulkenrol', $a); - $checkedemails->error_messages[$linecnt] = $error; - - // One email in row/line. - } else if ($emailsinlinecnt == 1) { - $email = $emailline; - local_bulkenrol_check_email($email, $linecnt, $courseid, $context, $currentgroup, $checkedemails); + // Check delimiters. + foreach ($possibledelimiters as $possibledelimiter) { + $pos = strpos($dataline, $possibledelimiter); + if ($pos) { + $delimiter = $possibledelimiter; + break; } - // More than one email in row/line. - if ($emailsinlinecnt > 1) { - $delimiter = ''; - - // Check delimiters. - foreach ($emaildelimiters as $emaildelimiter) { - $pos = strpos($emailline, $emaildelimiter); - if ($pos) { - $delimiter = $emaildelimiter; - break; - } - } - if (!empty($delimiter)) { - $emailsinline = explode($delimiter, $emailline); - - // Iterate emails in row/line. - foreach ($emailsinline as $emailinline) { + } + if (empty($delimiter)) { + // Could possibly be only one students data. + local_bulkenrol_check_data($dataline, $datafield, $linecnt, $courseid, $context, $currentgroup, $checkeddata); + } else { + $alldatainline = explode($delimiter, $dataline); - $email = trim($emailinline); - local_bulkenrol_check_email($email, $linecnt, $courseid, $context, $currentgroup, $checkedemails); - } - } + // Iterate over students data in row/line. + foreach ($alldatainline as $datainline) { + $data = trim($datainline); + local_bulkenrol_check_data($data, $linecnt, $datafield, $courseid, $context, $currentgroup, $checkeddata); } } } - return $checkedemails; + return $checkeddata; } /** * - * Check submitted email, working on the $checkedemails array + * Check submitted user data, working on the $checkeddata array * - * @param string $email e-mail of the user that should be enroled + * @param string $data identifying data of the user that should be enroled + * @param string $datafield To which database field to compare the user data. + * u_* for Fields of the user-table, c_* for custom fields. * @param int $linecnt line counter used for error messages * @param int $courseid course id * @param context_course $context context instance of the course the user should be enroled into * @param string $currentgroup name of the group a user should be added to as member - * @param object $checkedemails Object containing information to be displayed on confirm page and being used for bulkenrol. + * @param object $checkeddata Object containing information to be displayed on confirm page and being used for bulkenrol. */ -function local_bulkenrol_check_email($email, $linecnt, $courseid, $context, $currentgroup, &$checkedemails) { - // Check for valid email. - $emailisvalid = validate_email($email); - // Email is not valid. - if (!$emailisvalid) { - $checkedemails->emails_to_ignore[] = $email; - $a = new stdClass(); - $a->row = $linecnt; - $a->email = $email; - $error = get_string('error_invalid_email', 'local_bulkenrol', $a); - if (array_key_exists($linecnt, $checkedemails->error_messages)) { - $errors = $checkedemails->error_messages[$linecnt]; - $errors .= "
".$error; - $checkedemails->error_messages[$linecnt] = $errors; +function local_bulkenrol_check_data($data, $datafield, $linecnt, $courseid, $context, $currentgroup, &$checkeddata) { + // Check for moodle user with specified data. + list($error, $userrecord) = local_bulkenrol_get_user($data, $datafield); + if (!empty($error)) { + $checkeddata->data_to_ignore[] = $data; + if (array_key_exists($linecnt, $checkeddata->error_messages)) { + $errors = $checkeddata->error_messages[$linecnt]; + $errors .= "
" . $error; + $checkeddata->error_messages[$linecnt] = $errors; } else { - $checkedemails->error_messages[$linecnt] = $error; + $checkeddata->error_messages[$linecnt] = $error; } - - // Email is valid. - } else { - // Check for moodle user with email. - list($error, $userrecord) = local_bulkenrol_get_user($email); - if (!empty($error)) { - $checkedemails->emails_to_ignore[] = $email; - if (array_key_exists($linecnt, $checkedemails->error_messages)) { - $errors = $checkedemails->error_messages[$linecnt]; - $errors .= "
".$error; - $checkedemails->error_messages[$linecnt] = $errors; - } else { - $checkedemails->error_messages[$linecnt] = $error; - } - } else if (!empty($userrecord) && !empty($userrecord->id)) { - $checkedemails->validemailfound += 1; - - $useralreadyenroled = false; - if (!empty($context) && !empty($userrecord)) { - $useralreadyenroled = is_enrolled($context, $userrecord->id); - } - $checkedemails->moodleusers_for_email[$email] = $userrecord; - if (empty($useralreadyenroled)) { - $checkedemails->user_enroled[$email] = $userrecord; - } - if (!empty($currentgroup) && array_key_exists($currentgroup, $checkedemails->course_groups)) { - $checkedemails->course_groups[$currentgroup][] = $userrecord; - } - if (!array_key_exists($email, $checkedemails->user_groups)) { - $checkedemails->user_groups[$email] = array(); + } else if (!empty($userrecord) && !empty($userrecord->id)) { + $checkeddata->validusersfound += 1; + $useralreadyenroled = false; + if (!empty($context) && !empty($userrecord)) { + $useralreadyenroled = is_enrolled($context, $userrecord->id); + } + $checkeddata->moodleusers_for_data[$data] = $userrecord; + if (empty($useralreadyenroled)) { + $checkeddata->user_enroled[$data] = $userrecord; + } + if (!empty($currentgroup) && array_key_exists($currentgroup, $checkeddata->course_groups)) { + $checkeddata->course_groups[$currentgroup][$data] = $userrecord; + } + if (!array_key_exists($data, $checkeddata->user_groups)) { + $checkeddata->user_groups[$data] = array(); + } + if (!empty($currentgroup) && !array_key_exists($currentgroup, $checkeddata->user_groups[$data])) { + // Check if user is already member of the group. + $result = local_bulkenrol_is_already_member($courseid, $currentgroup, $userrecord->id); + if (!empty($result->error)) { + $a = new stdClass(); + $a->row = $linecnt; + $a->data = $data; + $a->groupname = $currentgroup; + $a->error = $result->error; + $error = get_string('error_check_is_already_member', 'local_bulkenrol', $a); + $checkeddata->error_messages[$linecnt] = $error; } - if (!empty($currentgroup) && !array_key_exists($currentgroup, $checkedemails->user_groups[$email])) { - // Check if user is already member of the group. - $result = local_bulkenrol_is_already_member($courseid, $currentgroup, $userrecord->id); - if (!empty($result->error)) { - $a = new stdClass(); - $a->row = $linecnt; - $a->email = $email; - $a->groupname = $currentgroup; - $a->error = $result->error; - $error = get_string('error_check_is_already_member', 'local_bulkenrol', $a); - $checkedemails->error_messages[$linecnt] = $error; - } - $alreadymember = $result->already_member; - // Compose group information. - if (empty($alreadymember)) { - $groupinfo = html_writer::tag('span', - get_string('user_groups_yes', 'local_bulkenrol'), - array('class' => 'badge badge-secondary')); - } else { - $groupinfo = html_writer::tag('span', - get_string('user_groups_already', 'local_bulkenrol'), - array('class' => 'badge badge-success')); - } - $checkedemails->user_groups[$email][] = $currentgroup .': '. $groupinfo; + $alreadymember = $result->already_member; + // Compose group information + if (empty($alreadymember)) { + $groupinfo = html_writer::tag('span', + get_string('user_groups_yes', 'local_bulkenrol'), + array('class' => 'badge badge-secondary')); + } else { + $groupinfo = html_writer::tag('span', + get_string('user_groups_already', 'local_bulkenrol'), + array('class' => 'badge badge-success')); } + $checkeddata->user_groups[$data][] = $currentgroup . $groupinfo; } } } /** - * Takes input from text area containing a list of e-mail adresses (optionally group names starting with '#'). + * Takes input from text area containing a list of data that specifies users (optionally group names starting with '#'). * Returns an array representation of the input. * - * @param mixed $emails input value of the text area. - * @return string[] of e-emails and optional group names + * @param mixed $data input value of the text area. + * @return string[] of data and optional group names */ -function local_bulkenrol_parse_emails($emails) { - if (empty($emails)) { +function local_bulkenrol_parse_data($data) { + if (empty($data)) { return array(); } else { - $rawlines = explode(PHP_EOL, $emails); + $rawlines = explode(PHP_EOL, $data); $result = array(); foreach ($rawlines as $rawline) { $result[] = trim($rawline); @@ -239,38 +209,52 @@ function local_bulkenrol_parse_emails($emails) { /** * Takes an e-mail and returns a moodle user record and error string (if occured). * - * @param string $email E-mail used to search for a user - * @return string,object[] + * @param string $data Data used to search for a user + * @param string $datafield To which database field to compare the user data. + * u_* for Fields of the user-table, c_* for custom fields. + * @return array [string,object[]] */ -function local_bulkenrol_get_user($email) { +function local_bulkenrol_get_user($data, $datafield) { global $DB; $error = null; $userrecord = null; - if (empty($email)) { + if (empty($data)) { + $error = get_string('error_no_data', 'local_bulkenrol', $data); return array($error, $userrecord); - } else { - // Get user records for email. - try { - $userrecords = $DB->get_records('user', array('email' => $email)); - $count = count($userrecords); - if (!empty($count)) { - // More than one user with email -> ignore email and don't enrol users later! - if ($count > 1) { - $error = get_string('error_more_than_one_record_for_email', 'local_bulkenrol', $email); - } else { - $userrecord = current($userrecords); - } + } + + // Get user records for data. + try { + $prefix = substr($datafield, 0, 2); + $usertablefield = substr($datafield, 2, strlen($datafield) - 2); + if ($prefix === 'u_') { + $userrecords = $DB->get_records('user', array($usertablefield => $data)); + } else if ($prefix === 'c_') { + $userrecords = $DB->get_records_sql( + 'SELECT u.* FROM {user} u ' . + 'JOIN {user_info_data} data ON data.userid = u.id ' . + 'WHERE data.fieldid = :fieldid AND data.data = :data', + array('fieldid' => $usertablefield, 'data' => $data)); + } + + $count = count($userrecords); + if (!empty($count)) { + // More than one user with data -> ignore data and don't enrol users later! + if ($count > 1) { + $error = get_string('error_more_than_one_record_for_data', 'local_bulkenrol', array('identifier' => $data, "field" => $datafield)); } else { - $error = get_string('error_no_record_found_for_email', 'local_bulkenrol', $email); + $userrecord = current($userrecords); } - } catch (Exception $e) { - $error = get_string('error_getting_user_for_email', 'local_bulkenrol', $email).local_bulkenrol_get_exception_info($e); + } else { + $error = get_string('error_no_record_found_for_data', 'local_bulkenrol', $data); } - - return array($error, $userrecord); + } catch (Exception $e) { + $error = get_string('error_getting_user_for_data', 'local_bulkenrol', $data) . local_bulkenrol_get_exception_info($e); } + + return array($error, $userrecord); } /** @@ -313,7 +297,7 @@ function local_bulkenrol_users($localbulkenrolkey) { $courseid = $tmpdata[0]; } - $userstoenrol = $localbulkenroldata->moodleusers_for_email; + $userstoenrol = $localbulkenroldata->moodleusers_for_data; if (!empty($courseid) && !empty($userstoenrol)) { try { @@ -364,7 +348,7 @@ function local_bulkenrol_users($localbulkenrolkey) { // Get the course context. $coursecontext = context_course::instance($courseid); - foreach ($userstoenrol as $user) { + foreach ($userstoenrol as $data => $user) { try { // Check if user is already enrolled with another enrolment method. $userisenrolled = is_enrolled($coursecontext, $user->id, '', false); @@ -379,7 +363,7 @@ function local_bulkenrol_users($localbulkenrolkey) { } } catch (Exception $e) { $a = new stdClass(); - $a->email = $user->email; + $a->data = $data; $msg = get_string('error_enrol_user', 'local_bulkenrol', $a). local_bulkenrol_get_exception_info($e); @@ -427,14 +411,14 @@ function local_bulkenrol_users($localbulkenrolkey) { if (empty($useradded)) { $a = new stdClass(); - $a->email = $member->email; + $a->data = $key; $a->group = $groupname; $msg = get_string('error_group_add_member', 'local_bulkenrol', $a); $exceptionsmsg[] = $msg; } } catch (Exception $e) { $a = new stdClass(); - $a->email = $member->email; + $a->data = $key; $a->group = $groupname; $msg = get_string('error_group_add_member', 'local_bulkenrol', $a). local_bulkenrol_get_exception_info($e); @@ -530,14 +514,14 @@ function local_bulkenrol_display_table($localbulkenroldata, $key) { break; case LOCALBULKENROL_ENROLUSERS: - $data = array(); + $rowdata = array(); - if (!empty($localbulkenroldata->moodleusers_for_email)) { - foreach ($localbulkenroldata->moodleusers_for_email as $email => $user) { + if (!empty($localbulkenroldata->moodleusers_for_data)) { + foreach ($localbulkenroldata->moodleusers_for_data as $data => $user) { $row = array(); $cell = new html_table_cell(); - $cell->text = $user->email; + $cell->text = $data; $row[] = $cell; $cell = new html_table_cell(); @@ -550,7 +534,7 @@ function local_bulkenrol_display_table($localbulkenroldata, $key) { $cell = new html_table_cell(); $cell->text = ''; - if (!empty($localbulkenroldata->user_enroled[$email])) { + if (!empty($localbulkenroldata->user_enroled[$data])) { $cell->text = html_writer::tag('span', get_string('user_enroled_yes', 'local_bulkenrol'), array('class' => 'badge badge-secondary')); @@ -563,12 +547,12 @@ function local_bulkenrol_display_table($localbulkenroldata, $key) { $cell = new html_table_cell(); $cell->text = ''; - if (!empty($localbulkenroldata->user_groups[$email])) { - $cell->text = implode(',
', $localbulkenroldata->user_groups[$email]); + if (!empty($localbulkenroldata->user_groups[$data])) { + $cell->text = implode(',
', $localbulkenroldata->user_groups[$data]); } $row[] = $cell; - $data[] = $row; + $rowdata[] = $row; } } @@ -578,14 +562,14 @@ function local_bulkenrol_display_table($localbulkenroldata, $key) { $table->summary = get_string('users_to_enrol_in_course', 'local_bulkenrol'); $table->size = array('20%', '17%', '17%', '20%', '26%'); $table->head = array(); - $table->head[] = get_string('email'); + $table->head[] = get_string('identifying_data', 'local_bulkenrol'); $table->head[] = get_string('firstname'); $table->head[] = get_string('lastname'); $table->head[] = get_string('user_enroled', 'local_bulkenrol'); $table->head[] = get_string('user_groups', 'local_bulkenrol'); - $table->data = $data; + $table->data = $rowdata; - if (!empty($data)) { + if (!empty($rowdata)) { echo $OUTPUT->heading(get_string('users_to_enrol_in_course', 'local_bulkenrol'), 3); echo html_writer::tag('div', html_writer::table($table), array('class' => 'flexible-wrap')); } @@ -704,7 +688,7 @@ function local_bulkenrol_is_already_member($courseid, $groupname, $userid) { } } catch (Exception $e) { $msg = get_string('error_group_add_members', 'local_bulkenrol').local_bulkenrol_get_exception_info($e); - $exceptionsmsg[] = $msg; + $result->error = $msg; } return $result; } diff --git a/settings.php b/settings.php index bc12601..e396114 100644 --- a/settings.php +++ b/settings.php @@ -24,6 +24,18 @@ defined('MOODLE_INTERNAL') || die; +$filtercustombyunique = true; + +$usertableoptions = [ + "email", + "idnumber", + "username" +]; + +$standardoptions = [ + "u_email" +]; + if ($hassiteconfig) { $settings = new admin_settingpage('local_bulkenrol', get_string('pluginname', 'local_bulkenrol', null, true)); @@ -44,6 +56,7 @@ ); unset($enroloptions); + // Create role chooser widget. $roleoptions = array(); // Get some basic data we are going to need. @@ -74,6 +87,32 @@ $roleoptions) ); unset($roleoptions); + + global $DB; + $fields = []; + foreach ($usertableoptions as $fieldname) { + if (!in_array($fieldname, $usertableoptions)) { + continue; + } + $fields["u_" . $fieldname] = $fieldname; + } + + $sql = "SELECT id, name, forceunique FROM {user_info_field} WHERE forceunique = 1"; + $customfields = $DB->get_records_sql_menu($sql); + + foreach ($customfields as $id => $name) { + $fields["c_" . $id] = $name; + } + + $settings->add( + new admin_setting_configmultiselect( + 'local_bulkenrol/fieldoptions', + get_string('fieldoptions', 'local_bulkenrol'), + get_string('fieldoptions_desc', 'local_bulkenrol'), + $standardoptions, + $fields + ) + ); } $ADMIN->add('enrolments', $settings); diff --git a/tests/behat/local_bulkenrol_groups.feature b/tests/behat/local_bulkenrol_groups.feature index 77b7cf6..7edbe34 100644 --- a/tests/behat/local_bulkenrol_groups.feature +++ b/tests/behat/local_bulkenrol_groups.feature @@ -20,6 +20,7 @@ Feature: Using the local_bulkenrol plugin for group management And the following config values are set as admin: | config | value | plugin | | enrolplugin | manual | local_bulkenrol | + | fieldoptions | u_email,u_idnumber,u_username | local_bulkenrol | Given I log in as "admin" And I navigate to "Plugins > Enrolments > User bulk enrolment" in site administration And I set the following fields to these values: @@ -39,7 +40,7 @@ Feature: Using the local_bulkenrol plugin for group management When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ # Group 1 student1@example.com @@ -78,7 +79,7 @@ Feature: Using the local_bulkenrol plugin for group management When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ # Group 1 student1@example.com @@ -116,7 +117,7 @@ Feature: Using the local_bulkenrol plugin for group management When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ # Group 1 student1@example.com @@ -145,7 +146,7 @@ Feature: Using the local_bulkenrol plugin for group management When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ # Group 1 student1@example.com diff --git a/tests/behat/local_bulkenrol_users.feature b/tests/behat/local_bulkenrol_users.feature index 3d12b81..bd1a2d1 100644 --- a/tests/behat/local_bulkenrol_users.feature +++ b/tests/behat/local_bulkenrol_users.feature @@ -9,17 +9,18 @@ Feature: Using the local_bulkenrol plugin for user enrolments | fullname | shortname | format | | Course 1 | C1 | topics | And the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | Teacher | 1 | teacher1@example.com | - | student1 | Student | 1 | student1@example.com | - | student2 | Student | 2 | student2@example.com | - | student3 | Student | 3 | student3@example.com | + | username | firstname | lastname | email | idnumber | + | teacher1 | Teacher | 1 | teacher1@example.com | 1 | + | student1 | Student | 1 | student1@example.com | 2 | + | student2 | Student | 2 | student2@example.com | 3 | + | student3 | Student | 3 | student3@example.com | 4 | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | And the following config values are set as admin: | config | value | plugin | | enrolplugin | manual | local_bulkenrol | + | fieldoptions | u_email,u_idnumber,u_username | local_bulkenrol | Given I log in as "admin" And I navigate to "Plugins > Enrolments > User bulk enrolment" in site administration And I set the following fields to these values: @@ -37,7 +38,7 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ student1@example.com student2@example.com @@ -65,7 +66,7 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ student1@example.com student2@example.com @@ -99,7 +100,7 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ student1@example.com student2@example.com @@ -123,6 +124,77 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I click on "[data-enrolinstancename='Manual enrolments'] a[data-action=showdetails]" "css_element" in the "Student 1" "table_row" Then I should see "Manual enrolments" + Scenario: Bulk enrol users into the course by their ID + Given I log in as "admin" + And I navigate to "Plugins > Enrolments > User bulk enrolment" in site administration + And I set the following fields to these values: + | Fieldoptions | idnumber,email,username | + And I press "Save changes" + And I log out + When I log in as "teacher1" + And I am on "Course 1" course homepage + And I navigate to "Users > User bulk enrolment" in current page administration + Then the "dbfield" select box should contain "email" + And the "dbfield" select box should contain "idnumber" + And the "dbfield" select box should contain "username" + And I set the field "List of users identified by your chosen field" to multiline: + """ + 2 + 3 + 4 + """ + And I click on "Enrol users" "button" + Then the following should exist in the "localbulkenrol_enrolusers" table: + | idnumber | First name | Surname | User enrolment | + | 1 | Student | 1 | User will be enrolled | + | 2 | Student | 2 | User will be enrolled | + | 3 | Student | 3 | User will be enrolled | + And the following should exist in the "localbulkenrol_enrolinfo" table: + | Enrolment method | Assigned role | + | Manual enrolments | Student | + And I click on "Enrol users" "button" + Then the following should exist in the "participants" table: + | Email address | First name | Surname | Roles | + | student1@example.com | Student | 1 | Student | + | student2@example.com | Student | 2 | Student | + | student3@example.com | Student | 3 | Student | + When I click on "[data-enrolinstancename='Manual enrolments'] a[data-action=showdetails]" "css_element" in the "Student 1" "table_row" + Then I should see "Manual enrolments" + + Scenario: Bulk enrol students when there is only a single datafield option. It should automatically change the helptext. + Given I log in as "admin" + And I navigate to "Plugins > Enrolments > User bulk enrolment" in site administration + And I set the following fields to these values: + | Fieldoptions | email | + And I press "Save changes" + And I log out + When I log in as "teacher1" + And I am on "Course 1" course homepage + And I navigate to "Users > User bulk enrolment" in current page administration + And I set the field "List of users identified by their email" to multiline: + """ + student1@example.com + student2@example.com + student3@example.com + """ + And I click on "Enrol users" "button" + Then the following should exist in the "localbulkenrol_enrolusers" table: + | idnumber | First name | Surname | User enrolment | + | 1 | Student | 1 | User will be enrolled | + | 2 | Student | 2 | User will be enrolled | + | 3 | Student | 3 | User will be enrolled | + And the following should exist in the "localbulkenrol_enrolinfo" table: + | Enrolment method | Assigned role | + | Manual enrolments | Student | + And I click on "Enrol users" "button" + Then the following should exist in the "participants" table: + | Email address | First name | Surname | Roles | + | student1@example.com | Student | 1 | Student | + | student2@example.com | Student | 2 | Student | + | student3@example.com | Student | 3 | Student | + When I click on "[data-enrolinstancename='Manual enrolments'] a[data-action=showdetails]" "css_element" in the "Student 1" "table_row" + Then I should see "Manual enrolments" + Scenario: Bulk enrol students into the course with students already enrolled Given the following "course enrolments" exist: | user | course | role | @@ -130,7 +202,7 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ student1@example.com student2@example.com @@ -164,7 +236,7 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ student1@example.com """ @@ -183,23 +255,23 @@ Feature: Using the local_bulkenrol plugin for user enrolments When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ student4@example.com """ And I click on "Enrol users" "button" - Then I should see "No existing Moodle user account with e-mail address student4@example.com." + Then I should see "No existing Moodle user account student4@example.com was found." Scenario: Try to bulk enrol a list of invalid users. When I log in as "teacher1" And I am on "Course 1" course homepage And I navigate to "Users > User bulk enrolment" in current page administration - And I set the field "List of e-mail addresses" to multiline: + And I set the field "List of users identified by your chosen field" to multiline: """ foo bar """ And I click on "Enrol users" "button" - Then I should see "No valid e-mail address was found in the given list." + Then I should see " No valid entrys were found in the given list." And I should see "Please go back and check your input" And "Enrol users" "button" should not exist