first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file processes AJAX enrolment actions and returns JSON for the manual enrolments plugin
*
* The general idea behind this file is that any errors should throw exceptions
* which will be returned and acted upon by the calling AJAX script.
*
* @package enrol_manual
* @copyright 2010 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('AJAX_SCRIPT', true);
require('../../config.php');
require_once($CFG->dirroot.'/enrol/locallib.php');
require_once($CFG->dirroot.'/group/lib.php');
require_once($CFG->dirroot.'/enrol/manual/locallib.php');
require_once($CFG->dirroot.'/cohort/lib.php');
require_once($CFG->dirroot . '/enrol/manual/classes/enrol_users_form.php');
$id = required_param('id', PARAM_INT); // Course id.
$action = required_param('action', PARAM_ALPHANUMEXT);
$PAGE->set_url(new moodle_url('/enrol/ajax.php', array('id'=>$id, 'action'=>$action)));
$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
$context = context_course::instance($course->id, MUST_EXIST);
if ($course->id == SITEID) {
throw new moodle_exception('invalidcourse');
}
require_login($course);
require_capability('moodle/course:enrolreview', $context);
require_sesskey();
echo $OUTPUT->header(); // Send headers.
$manager = new course_enrolment_manager($PAGE, $course);
$outcome = new stdClass();
$outcome->success = true;
$outcome->response = new stdClass();
$outcome->error = '';
$outcome->count = 0;
$searchanywhere = get_user_preferences('userselector_searchtype') === USER_SEARCH_CONTAINS;
switch ($action) {
case 'enrol':
$enrolid = required_param('enrolid', PARAM_INT);
$cohorts = $users = [];
$userids = optional_param_array('userlist', [], PARAM_SEQUENCE);
$userid = optional_param('userid', 0, PARAM_INT);
if ($userid) {
$userids[] = $userid;
}
if ($userids) {
foreach ($userids as $userid) {
$users[] = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
}
}
$cohortids = optional_param_array('cohortlist', [], PARAM_SEQUENCE);
$cohortid = optional_param('cohortid', 0, PARAM_INT);
if ($cohortid) {
$cohortids[] = $cohortid;
}
if ($cohortids) {
foreach ($cohortids as $cohortid) {
$cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
if (!cohort_can_view_cohort($cohort, $context)) {
throw new enrol_ajax_exception('invalidenrolinstance'); // TODO error text!
}
$cohorts[] = $cohort;
}
}
$roleid = optional_param('roletoassign', null, PARAM_INT);
$duration = optional_param('duration', 0, PARAM_INT);
$startdate = optional_param('startdate', 0, PARAM_INT);
$recovergrades = optional_param('recovergrades', 0, PARAM_INT);
$timeend = optional_param_array('timeend', [], PARAM_INT);
if (empty($roleid)) {
$roleid = null;
} else {
if (!has_capability('moodle/role:assign', $context)) {
throw new enrol_ajax_exception('assignnotpermitted');
}
if (!array_key_exists($roleid, get_assignable_roles($context, ROLENAME_ALIAS, false))) {
throw new enrol_ajax_exception('invalidrole');
}
}
if (empty($startdate)) {
if (!$startdate = get_config('enrol_manual', 'enrolstart')) {
// Default to now if there is no system setting.
$startdate = 4;
}
}
switch($startdate) {
case 2:
$timestart = $course->startdate;
break;
case 4:
// We mimic get_enrolled_sql round(time(), -2) but always floor as we want users to always access their
// courses once they are enrolled.
$timestart = intval(substr(time(), 0, 8) . '00') - 1;
break;
case 3:
default:
$today = time();
$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
$timestart = $today;
break;
}
if ($timeend) {
$timeend = make_timestamp($timeend['year'], $timeend['month'], $timeend['day'], $timeend['hour'], $timeend['minute']);
} else if ($duration <= 0) {
$timeend = 0;
} else {
$timeend = $timestart + $duration;
}
$mform = new enrol_manual_enrol_users_form(null, (object)["context" => $context]);
$userenroldata = [
'startdate' => $timestart,
'timeend' => $timeend,
];
$mform->set_data($userenroldata);
$validationerrors = $mform->validation($userenroldata, null);
if (!empty($validationerrors)) {
throw new enrol_ajax_exception('invalidenrolduration');
}
$instances = $manager->get_enrolment_instances();
$plugins = $manager->get_enrolment_plugins(true); // Do not allow actions on disabled plugins.
if (!array_key_exists($enrolid, $instances)) {
throw new enrol_ajax_exception('invalidenrolinstance');
}
$instance = $instances[$enrolid];
if (!isset($plugins[$instance->enrol])) {
throw new enrol_ajax_exception('enrolnotpermitted');
}
$plugin = $plugins[$instance->enrol];
if ($plugin->allow_enrol($instance) && has_capability('enrol/'.$plugin->get_name().':enrol', $context)) {
foreach ($users as $user) {
$plugin->enrol_user($instance, $user->id, $roleid, $timestart, $timeend, null, $recovergrades);
}
$outcome->count += count($users);
foreach ($cohorts as $cohort) {
$totalenrolledusers = $plugin->enrol_cohort($instance, $cohort->id, $roleid, $timestart, $timeend, null, $recovergrades);
$outcome->count += $totalenrolledusers;
}
} else {
throw new enrol_ajax_exception('enrolnotpermitted');
}
$outcome->success = true;
break;
default:
throw new enrol_ajax_exception('unknowajaxaction');
}
echo json_encode($outcome);
@@ -0,0 +1,10 @@
/**
* Potential user selector module.
*
* @module enrol_manual/form-potential-user-selector
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("enrol_manual/form-potential-user-selector",["jquery","core/ajax","core/templates","core/str"],(function($,Ajax,Templates,Str){return{processResults:function(selector,results){var users=[];return $.isArray(results)?($.each(results,(function(index,user){users.push({value:user.id,label:user._label})})),users):results},transport:function(selector,query,success,failure){var courseid=$(selector).attr("courseid"),userfields=$(selector).attr("userfields").split(",");void 0===courseid&&(courseid="1");var enrolid=$(selector).attr("enrolid");void 0===enrolid&&(enrolid="");var perpage=parseInt($(selector).attr("perpage"));isNaN(perpage)&&(perpage=100),Ajax.call([{methodname:"core_enrol_get_potential_users",args:{courseid:courseid,enrolid:enrolid,search:query,searchanywhere:!0,page:0,perpage:perpage+1}}])[0].then((function(results){var promises=[],i=0;if(results.length<=perpage){const profileRegex=/^profile_field_(.*)$/;return $.each(results,(function(index,user){var ctx=user,identity=[];$.each(userfields,(function(i,k){const result=profileRegex.exec(k);result?user.customfields&&user.customfields.forEach((function(customfield){customfield.shortname===result[1]&&(ctx.hasidentity=!0,identity.push(customfield.value))})):void 0!==user[k]&&""!==user[k]&&(ctx.hasidentity=!0,identity.push(user[k]))})),ctx.identity=identity.join(", "),promises.push(Templates.render("enrol_manual/form-user-selector-suggestion",ctx))})),$.when.apply($.when,promises).then((function(){var args=arguments;$.each(results,(function(index,user){user._label=args[i],i++})),success(results)}))}return Str.get_string("toomanyuserstoshow","core",">"+perpage).then((function(toomanyuserstoshow){success(toomanyuserstoshow)}))})).fail(failure)}}}));
//# sourceMappingURL=form-potential-user-selector.min.js.map
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
define("enrol_manual/quickenrolment",["exports","core_table/dynamic","core/str","core/toast","core/config","core/fragment","core/modal_events","core/notification","jquery","core/pending","core/prefetch","core/modal_save_cancel"],(function(_exports,DynamicTable,Str,Toast,_config,_fragment,_modal_events,_notification,_jquery,_pending,_prefetch,_modal_save_cancel){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}
/**
* Quick enrolment AMD module.
*
* @module enrol_manual/quickenrolment
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,DynamicTable=_interopRequireWildcard(DynamicTable),Str=_interopRequireWildcard(Str),Toast=_interopRequireWildcard(Toast),_config=_interopRequireDefault(_config),_fragment=_interopRequireDefault(_fragment),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_jquery=_interopRequireDefault(_jquery),_pending=_interopRequireDefault(_pending),_prefetch=_interopRequireDefault(_prefetch),_modal_save_cancel=_interopRequireDefault(_modal_save_cancel);const Selectors_cohortSelector="#id_cohortlist",Selectors_triggerButtons=".enrolusersbutton.enrol_manual_plugin [type='submit']",Selectors_unwantedHiddenFields="input[value='_qf__force_multiselect_submission']",Selectors_buttonWrapper='[data-region="wrapper"]',getBodyForContext=contextId=>_fragment.default.loadFragment("enrol_manual","enrol_users_form",contextId,{}),registerEventListeners=contextId=>{document.addEventListener("click",(e=>{if(e.target.closest(Selectors_triggerButtons))return e.preventDefault(),void showModal((element=>{const wrapper=element.closest(Selectors_buttonWrapper);return DynamicTable.getTableFromId(wrapper.dataset.tableUniqueid)})(e.target),contextId)}))},showModal=(dynamicTable,contextId)=>{const pendingPromise=new _pending.default("enrol_manual/quickenrolment:showModal");return _modal_save_cancel.default.create({large:!0,title:Str.get_string("enrolusers","enrol_manual"),body:getBodyForContext(contextId),buttons:{save:Str.get_string("enrolusers","enrol_manual")},show:!0}).then((modal=>(modal.getRoot().on(_modal_events.default.save,(e=>{e.preventDefault(),modal.getRoot().find("form").submit()})),modal.getRoot().on("submit","form",(e=>{e.preventDefault(),submitFormAjax(dynamicTable,modal)})),modal.getRoot().on(_modal_events.default.hidden,(()=>{modal.destroy()})),modal))).then((modal=>Promise.all([modal,modal.getBodyPromise()]))).then((_ref=>{let[modal,body]=_ref;return body.get(0).querySelector(Selectors_cohortSelector)?modal.setSaveButtonText(Str.get_string("enroluserscohorts","enrol_manual")).then((()=>modal)):modal})).then((modal=>(pendingPromise.resolve(),modal))).catch(_notification.default.exception)},submitFormAjax=(dynamicTable,modal)=>{const form=modal.getRoot().find("form");form.get(0).querySelectorAll(Selectors_unwantedHiddenFields).forEach((hiddenField=>hiddenField.remove())),modal.hide(),modal.destroy(),_jquery.default.ajax("".concat(_config.default.wwwroot,"/enrol/manual/ajax.php?").concat(form.serialize()),{type:"GET",processData:!1,contentType:"application/json"}).then((response=>{if(response.error)throw new Error(response.error);return response.count})).then((count=>Promise.all([Str.get_string("totalenrolledusers","enrol",count),DynamicTable.refreshTableContent(dynamicTable)]))).then((_ref2=>{let[notificationBody]=_ref2;return notificationBody})).then((notificationBody=>Toast.add(notificationBody))).catch((error=>{_notification.default.addNotification({message:error.message,type:"error"})}))};_exports.init=_ref3=>{let{contextid:contextid}=_ref3;registerEventListeners(contextid),_prefetch.default.prefetchStrings("enrol_manual",["enrolusers","enroluserscohorts"]),_prefetch.default.prefetchString("enrol","totalenrolledusers")}}));
//# sourceMappingURL=quickenrolment.min.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,128 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Potential user selector module.
*
* @module enrol_manual/form-potential-user-selector
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/ajax', 'core/templates', 'core/str'], function($, Ajax, Templates, Str) {
return /** @alias module:enrol_manual/form-potential-user-selector */ {
processResults: function(selector, results) {
var users = [];
if ($.isArray(results)) {
$.each(results, function(index, user) {
users.push({
value: user.id,
label: user._label
});
});
return users;
} else {
return results;
}
},
transport: function(selector, query, success, failure) {
var promise;
var courseid = $(selector).attr('courseid');
var userfields = $(selector).attr('userfields').split(',');
if (typeof courseid === "undefined") {
courseid = '1';
}
var enrolid = $(selector).attr('enrolid');
if (typeof enrolid === "undefined") {
enrolid = '';
}
var perpage = parseInt($(selector).attr('perpage'));
if (isNaN(perpage)) {
perpage = 100;
}
promise = Ajax.call([{
methodname: 'core_enrol_get_potential_users',
args: {
courseid: courseid,
enrolid: enrolid,
search: query,
searchanywhere: true,
page: 0,
perpage: perpage + 1
}
}]);
promise[0].then(function(results) {
var promises = [],
i = 0;
if (results.length <= perpage) {
// Render the label.
const profileRegex = /^profile_field_(.*)$/;
$.each(results, function(index, user) {
var ctx = user,
identity = [];
$.each(userfields, function(i, k) {
const result = profileRegex.exec(k);
if (result) {
if (user.customfields) {
user.customfields.forEach(function(customfield) {
if (customfield.shortname === result[1]) {
ctx.hasidentity = true;
identity.push(customfield.value);
}
});
}
} else {
if (typeof user[k] !== 'undefined' && user[k] !== '') {
ctx.hasidentity = true;
identity.push(user[k]);
}
}
});
ctx.identity = identity.join(', ');
promises.push(Templates.render('enrol_manual/form-user-selector-suggestion', ctx));
});
// Apply the label to the results.
return $.when.apply($.when, promises).then(function() {
var args = arguments;
$.each(results, function(index, user) {
user._label = args[i];
i++;
});
success(results);
return;
});
} else {
return Str.get_string('toomanyuserstoshow', 'core', '>' + perpage).then(function(toomanyuserstoshow) {
success(toomanyuserstoshow);
return;
});
}
}).fail(failure);
}
};
});
+200
View File
@@ -0,0 +1,200 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Quick enrolment AMD module.
*
* @module enrol_manual/quickenrolment
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import * as DynamicTable from 'core_table/dynamic';
import * as Str from 'core/str';
import * as Toast from 'core/toast';
import Config from 'core/config';
import Fragment from 'core/fragment';
import ModalEvents from 'core/modal_events';
import Notification from 'core/notification';
import jQuery from 'jquery';
import Pending from 'core/pending';
import Prefetch from 'core/prefetch';
import ModalSaveCancel from 'core/modal_save_cancel';
const Selectors = {
cohortSelector: "#id_cohortlist",
triggerButtons: ".enrolusersbutton.enrol_manual_plugin [type='submit']",
unwantedHiddenFields: "input[value='_qf__force_multiselect_submission']",
buttonWrapper: '[data-region="wrapper"]',
};
/**
* Get the content of the body for the specified context.
*
* @param {Number} contextId
* @returns {Promise}
*/
const getBodyForContext = contextId => {
return Fragment.loadFragment('enrol_manual', 'enrol_users_form', contextId, {});
};
/**
* Get the dynamic table for the button.
*
* @param {HTMLElement} element
* @returns {HTMLElement}
*/
const getDynamicTableForElement = element => {
const wrapper = element.closest(Selectors.buttonWrapper);
return DynamicTable.getTableFromId(wrapper.dataset.tableUniqueid);
};
/**
* Register the event listeners for this contextid.
*
* @param {Number} contextId
*/
const registerEventListeners = contextId => {
document.addEventListener('click', e => {
if (e.target.closest(Selectors.triggerButtons)) {
e.preventDefault();
showModal(getDynamicTableForElement(e.target), contextId);
return;
}
});
};
/**
* Display the modal for this contextId.
*
* @param {HTMLElement} dynamicTable The table to beb refreshed when changes are made
* @param {Number} contextId
* @returns {Promise}
*/
const showModal = (dynamicTable, contextId) => {
const pendingPromise = new Pending('enrol_manual/quickenrolment:showModal');
return ModalSaveCancel.create({
large: true,
title: Str.get_string('enrolusers', 'enrol_manual'),
body: getBodyForContext(contextId),
buttons: {
save: Str.get_string('enrolusers', 'enrol_manual'),
},
show: true,
})
.then(modal => {
modal.getRoot().on(ModalEvents.save, e => {
// Trigger a form submission, so that any mform elements can do final tricks before the form submission
// is processed.
// The actual submit even tis captured in the next handler.
e.preventDefault();
modal.getRoot().find('form').submit();
});
modal.getRoot().on('submit', 'form', e => {
e.preventDefault();
submitFormAjax(dynamicTable, modal);
});
modal.getRoot().on(ModalEvents.hidden, () => {
modal.destroy();
});
return modal;
})
.then(modal => Promise.all([modal, modal.getBodyPromise()]))
.then(([modal, body]) => {
if (body.get(0).querySelector(Selectors.cohortSelector)) {
return modal.setSaveButtonText(Str.get_string('enroluserscohorts', 'enrol_manual')).then(() => modal);
}
return modal;
})
.then(modal => {
pendingPromise.resolve();
return modal;
})
.catch(Notification.exception);
};
/**
* Submit the form via ajax.
*
* @param {HTMLElement} dynamicTable
* @param {Object} modal
*/
const submitFormAjax = (dynamicTable, modal) => {
// Note: We use a jQuery object here so that we can use its serialize functionality.
const form = modal.getRoot().find('form');
// Before send the data through AJAX, we need to parse and remove some unwanted hidden fields.
// This hidden fields are added automatically by mforms and when it reaches the AJAX we get an error.
form.get(0).querySelectorAll(Selectors.unwantedHiddenFields).forEach(hiddenField => hiddenField.remove());
modal.hide();
modal.destroy();
jQuery.ajax(
`${Config.wwwroot}/enrol/manual/ajax.php?${form.serialize()}`,
{
type: 'GET',
processData: false,
contentType: "application/json",
}
)
.then(response => {
if (response.error) {
throw new Error(response.error);
}
return response.count;
})
.then(count => {
return Promise.all([
Str.get_string('totalenrolledusers', 'enrol', count),
DynamicTable.refreshTableContent(dynamicTable),
]);
})
.then(([notificationBody]) => notificationBody)
.then(notificationBody => Toast.add(notificationBody))
.catch(error => {
Notification.addNotification({
message: error.message,
type: 'error',
});
});
};
/**
* Set up quick enrolment for the manual enrolment plugin.
*
* @param {Number} contextid The context id to setup for
*/
export const init = ({contextid}) => {
registerEventListeners(contextid);
Prefetch.prefetchStrings('enrol_manual', [
'enrolusers',
'enroluserscohorts',
]);
Prefetch.prefetchString('enrol', 'totalenrolledusers');
};
+43
View File
@@ -0,0 +1,43 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains form for bulk changing user enrolments.
*
* @package enrol_manual
* @copyright 2011 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once("$CFG->dirroot/enrol/bulkchange_forms.php");
/**
* The form to collect required information when bulk editing users enrolments.
*
* @copyright 2011 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_manual_editselectedusers_form extends enrol_bulk_enrolment_change_form {}
/**
* The form to confirm the intention to bulk delete users enrolments.
*
* @copyright 2011 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_manual_deleteselectedusers_form extends enrol_bulk_enrolment_confirm_form {}
+162
View File
@@ -0,0 +1,162 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Enrol users form.
*
* Simple form to search for users and add them using a manual enrolment to this course.
*
* @package enrol_manual
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/formslib.php');
class enrol_manual_enrol_users_form extends moodleform {
/**
* Form definition.
* @return void
*/
public function definition() {
global $PAGE, $DB, $CFG;
require_once($CFG->dirroot . '/enrol/locallib.php');
$context = $this->_customdata->context;
// Get the course and enrolment instance.
$coursecontext = $context->get_course_context();
$course = $DB->get_record('course', ['id' => $coursecontext->instanceid]);
$manager = new course_enrolment_manager($PAGE, $course);
$instance = null;
foreach ($manager->get_enrolment_instances() as $tempinstance) {
if ($tempinstance->enrol == 'manual') {
if ($instance === null) {
$instance = $tempinstance;
break;
}
}
}
$mform = $this->_form;
$mform->setDisableShortforms();
$mform->disable_form_change_checker();
$periodmenu = enrol_get_period_list();
// Work out the apropriate default settings.
$defaultperiod = $instance->enrolperiod;
if ($instance->enrolperiod > 0 && !isset($periodmenu[$instance->enrolperiod])) {
$periodmenu[$instance->enrolperiod] = format_time($instance->enrolperiod);
}
if (empty($extendbase)) {
if (!$extendbase = get_config('enrol_manual', 'enrolstart')) {
// Default to now if there is no system setting.
$extendbase = 4;
}
}
// Build the list of options for the starting from dropdown.
$now = time();
$today = make_timestamp(date('Y', $now), date('m', $now), date('d', $now), 0, 0, 0);
$dateformat = get_string('strftimedatefullshort');
// Enrolment start.
$basemenu = array();
if ($course->startdate > 0) {
$basemenu[2] = get_string('coursestart') . ' (' . userdate($course->startdate, $dateformat) . ')';
}
$basemenu[3] = get_string('today') . ' (' . userdate($today, $dateformat) . ')';
$basemenu[4] = get_string('now', 'enrol_manual') . ' (' . userdate($now, get_string('strftimedatetimeshort')) . ')';
$mform->addElement('header', 'main', get_string('enrolmentoptions', 'enrol'));
$options = array(
'ajax' => 'enrol_manual/form-potential-user-selector',
'multiple' => true,
'courseid' => $course->id,
'enrolid' => $instance->id,
'perpage' => $CFG->maxusersperpage,
'userfields' => implode(',', \core_user\fields::get_identity_fields($context, true))
);
$mform->addElement('autocomplete', 'userlist', get_string('selectusers', 'enrol_manual'), array(), $options);
// Confirm the user can search for cohorts before displaying select.
if (has_capability('moodle/cohort:manage', $context) || has_capability('moodle/cohort:view', $context)) {
// Check to ensure there is at least one visible cohort before displaying the select box.
// Ideally it would be better to call external_api::call_external_function('core_cohort_search_cohorts')
// (which is used to populate the select box) instead of duplicating logic but there is an issue with globals
// being borked (in this case $PAGE) when combining the usage of fragments and call_external_function().
require_once($CFG->dirroot . '/cohort/lib.php');
$availablecohorts = cohort_get_cohorts($context->id, 0, 1, '');
$availablecohorts = $availablecohorts['cohorts'];
if (!($context instanceof context_system)) {
$availablecohorts = array_merge($availablecohorts,
cohort_get_available_cohorts($context, COHORT_ALL, 0, 1, ''));
}
if (!empty($availablecohorts)) {
$options = ['contextid' => $context->id, 'multiple' => true];
$mform->addElement('cohort', 'cohortlist', get_string('selectcohorts', 'enrol_manual'), $options);
}
}
$roles = get_assignable_roles($context, ROLENAME_BOTH);
$mform->addElement('select', 'roletoassign', get_string('assignrole', 'enrol_manual'), $roles);
$mform->setDefault('roletoassign', $instance->roleid);
$mform->addAdvancedStatusElement('main');
$mform->addElement('checkbox', 'recovergrades', get_string('recovergrades', 'enrol'));
$mform->setAdvanced('recovergrades');
$mform->setDefault('recovergrades', $CFG->recovergradesdefault);
$mform->addElement('select', 'startdate', get_string('startingfrom'), $basemenu);
$mform->setDefault('startdate', $extendbase);
$mform->setAdvanced('startdate');
$mform->addElement('select', 'duration', get_string('enrolperiod', 'enrol'), $periodmenu);
$mform->setDefault('duration', $defaultperiod);
$mform->setAdvanced('duration');
$mform->disabledIf('duration', 'timeend[enabled]', 'checked', 1);
$mform->addElement('date_time_selector', 'timeend', get_string('enroltimeend', 'enrol'), ['optional' => true]);
$mform->setAdvanced('timeend');
$mform->addElement('hidden', 'id', $course->id);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'action', 'enrol');
$mform->setType('action', PARAM_ALPHA);
$mform->addElement('hidden', 'enrolid', $instance->id);
$mform->setType('enrolid', PARAM_INT);
}
/**
* Validate the submitted form data.
*
* @param array $data array of ("fieldname"=>value) of submitted data
* @param array $files array of uploaded files "element_name"=>tmp_file_path
* @return array of "element_name"=>"error_description" if there are errors,
* or an empty array if everything is OK (true allowed for backwards compatibility too).
*/
public function validation($data, $files) {
$errors = parent::validation($data, $files);
if (!empty($data['startdate']) && !empty($data['timeend'])) {
if ($data['startdate'] >= $data['timeend']) {
$errors['timeend'] = get_string('enroltimeendinvalid', 'enrol');
}
}
return $errors;
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for enrol_manual.
*
* @package enrol_manual
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_manual\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for enrol_manual implementing null_provider.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
@@ -0,0 +1,58 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The send expiry notifications task.
*
* @package enrol_manual
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_manual\task;
defined('MOODLE_INTERNAL') || die();
/**
* The send expiry notifications task.
*
* @package enrol_manual
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class send_expiry_notifications extends \core\task\scheduled_task {
/**
* Name for this task.
*
* @return string
*/
public function get_name() {
return get_string('sendexpirynotificationstask', 'enrol_manual');
}
/**
* Run task for sending expiry notifications.
*/
public function execute() {
$enrol = enrol_get_plugin('manual');
$trace = new \text_progress_trace();
$enrol->send_expiry_notifications($trace);
}
}
@@ -0,0 +1,57 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Syncing enrolments task.
*
* @package enrol_manual
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_manual\task;
defined('MOODLE_INTERNAL') || die();
/**
* Syncing enrolments task.
*
* @package enrol_manual
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sync_enrolments extends \core\task\scheduled_task {
/**
* Name for this task.
*
* @return string
*/
public function get_name() {
return get_string('syncenrolmentstask', 'enrol_manual');
}
/**
* Run task for syncing enrolments.
*/
public function execute() {
$enrol = enrol_get_plugin('manual');
$trace = new \text_progress_trace();
$enrol->sync($trace);
}
}
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace enrol_manual;
/**
* Hook callbacks to get the enrolment information.
*
* @package enrol_manual
* @copyright 2024 Huong Nguyen <huongnv13@gmail.com>
* @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,
);
}
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI update for manual enrolments expiration.
*
* Notes:
* - it is required to use the web server account when executing PHP CLI scripts
* - you need to change the "www-data" to match the apache user account
* - use "su" if "sudo" not available
*
* @package enrol_manual
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../../config.php');
require_once("$CFG->libdir/clilib.php");
// Now get cli options.
list($options, $unrecognized) = cli_get_params(array('verbose'=>false, 'help'=>false), array('v'=>'verbose', 'h'=>'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
$help =
"Execute manual enrolments expiration sync and send notifications.
Options:
-v, --verbose Print verbose progress information
-h, --help Print out this help
Example:
\$ sudo -u www-data /usr/bin/php enrol/self/manual/sync.php
";
echo $help;
die;
}
if (!enrol_is_enabled('manual')) {
cli_error('enrol_manual plugin is disabled, synchronisation stopped', 2);
}
if (empty($options['verbose'])) {
$trace = new null_progress_trace();
} else {
$trace = new text_progress_trace();
}
/** @var $plugin enrol_manual_plugin */
$plugin = enrol_get_plugin('manual');
$result = $plugin->sync($trace, null);
$plugin->send_expiry_notifications($trace);
exit($result);
+76
View File
@@ -0,0 +1,76 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Capabilities for manual enrolment plugin.
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
/* Add, edit or remove manual enrol instance. */
'enrol/manual:config' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
)
),
/* Enrol anybody. */
'enrol/manual:enrol' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
)
),
/* Manage enrolments of users. */
'enrol/manual:manage' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
)
),
/* Unenrol anybody (including self) - watch out for data loss. */
'enrol/manual:unenrol' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
)
),
/* Unenrol self - watch out for data loss. */
'enrol/manual:unenrolself' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
)
),
);
+32
View File
@@ -0,0 +1,32 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Hook callbacks for enrol_manual
*
* @package enrol_manual
* @copyright 2024 Huong Nguyen <huongnv13@gmail.com>
* @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',
],
];
+31
View File
@@ -0,0 +1,31 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual enrol plugin installation script
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
function xmldb_enrol_manual_install() {
global $CFG;
}
+34
View File
@@ -0,0 +1,34 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Defines message providers for manual enrolments.
*
* @package enrol_manual
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$messageproviders = array (
'expiry_notification' => [
'defaults' => [
'popup' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED,
'email' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED,
],
],
);
+47
View File
@@ -0,0 +1,47 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual plugin external functions and service definitions.
*
* @package enrol_manual
* @category webservice
* @copyright 2011 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$functions = array(
// === enrol related functions ===
'enrol_manual_enrol_users' => array(
'classname' => 'enrol_manual_external',
'methodname' => 'enrol_users',
'classpath' => 'enrol/manual/externallib.php',
'description' => 'Manual enrol users',
'capabilities'=> 'enrol/manual:enrol',
'type' => 'write',
),
'enrol_manual_unenrol_users' => array(
'classname' => 'enrol_manual_external',
'methodname' => 'unenrol_users',
'classpath' => 'enrol/manual/externallib.php',
'description' => 'Manual unenrol users',
'capabilities'=> 'enrol/manual:unenrol',
'type' => 'write',
),
);
+49
View File
@@ -0,0 +1,49 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Task definition for enrol_manual.
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @package enrol_manual
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$tasks = array(
array(
'classname' => '\enrol_manual\task\sync_enrolments',
'blocking' => 0,
'minute' => '*/10',
'hour' => '*',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
'disabled' => 0
),
array(
'classname' => '\enrol_manual\task\send_expiry_notifications',
'blocking' => 0,
'minute' => '*/10',
'hour' => '*',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
'disabled' => 0
)
);
+39
View File
@@ -0,0 +1,39 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file keeps track of upgrades to the manual enrolment plugin
*
* @package enrol_manual
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
function xmldb_enrol_manual_upgrade($oldversion) {
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.2.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.4.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
+221
View File
@@ -0,0 +1,221 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
/**
* External course participation api.
*
* This api is mostly read only, the actual enrol and unenrol
* support is in each enrol plugin.
*
* @package enrol_manual
* @category external
* @copyright 2011 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.2
*/
class enrol_manual_external extends external_api {
/**
* Returns description of method parameters.
*
* @return external_function_parameters
* @since Moodle 2.2
*/
public static function enrol_users_parameters() {
return new external_function_parameters(
array(
'enrolments' => new external_multiple_structure(
new external_single_structure(
array(
'roleid' => new external_value(PARAM_INT, 'Role to assign to the user'),
'userid' => new external_value(PARAM_INT, 'The user that is going to be enrolled'),
'courseid' => new external_value(PARAM_INT, 'The course to enrol the user role in'),
'timestart' => new external_value(PARAM_INT, 'Timestamp when the enrolment start', VALUE_OPTIONAL),
'timeend' => new external_value(PARAM_INT, 'Timestamp when the enrolment end', VALUE_OPTIONAL),
'suspend' => new external_value(PARAM_INT, 'set to 1 to suspend the enrolment', VALUE_OPTIONAL)
)
)
)
)
);
}
/**
* Enrolment of users.
*
* Function throw an exception at the first error encountered.
* @param array $enrolments An array of user enrolment
* @since Moodle 2.2
*/
public static function enrol_users($enrolments) {
global $DB, $CFG;
require_once($CFG->libdir . '/enrollib.php');
$params = self::validate_parameters(self::enrol_users_parameters(),
array('enrolments' => $enrolments));
$transaction = $DB->start_delegated_transaction(); // Rollback all enrolment if an error occurs
// (except if the DB doesn't support it).
// Retrieve the manual enrolment plugin.
$enrol = enrol_get_plugin('manual');
if (empty($enrol)) {
throw new moodle_exception('manualpluginnotinstalled', 'enrol_manual');
}
foreach ($params['enrolments'] as $enrolment) {
// Ensure the current user is allowed to run this function in the enrolment context.
$context = context_course::instance($enrolment['courseid'], IGNORE_MISSING);
self::validate_context($context);
// Check that the user has the permission to manual enrol.
require_capability('enrol/manual:enrol', $context);
// Throw an exception if user is not able to assign the role.
$roles = get_assignable_roles($context);
if (!array_key_exists($enrolment['roleid'], $roles)) {
$errorparams = new stdClass();
$errorparams->roleid = $enrolment['roleid'];
$errorparams->courseid = $enrolment['courseid'];
$errorparams->userid = $enrolment['userid'];
throw new moodle_exception('wsusercannotassign', 'enrol_manual', '', $errorparams);
}
// Check manual enrolment plugin instance is enabled/exist.
$instance = null;
$enrolinstances = enrol_get_instances($enrolment['courseid'], true);
foreach ($enrolinstances as $courseenrolinstance) {
if ($courseenrolinstance->enrol == "manual") {
$instance = $courseenrolinstance;
break;
}
}
if (empty($instance)) {
$errorparams = new stdClass();
$errorparams->courseid = $enrolment['courseid'];
throw new moodle_exception('wsnoinstance', 'enrol_manual', '', $errorparams);
}
// Check that the plugin accept enrolment (it should always the case, it's hard coded in the plugin).
if (!$enrol->allow_enrol($instance)) {
$errorparams = new stdClass();
$errorparams->roleid = $enrolment['roleid'];
$errorparams->courseid = $enrolment['courseid'];
$errorparams->userid = $enrolment['userid'];
throw new moodle_exception('wscannotenrol', 'enrol_manual', '', $errorparams);
}
// Finally proceed the enrolment.
$enrolment['timestart'] = isset($enrolment['timestart']) ? $enrolment['timestart'] : 0;
$enrolment['timeend'] = isset($enrolment['timeend']) ? $enrolment['timeend'] : 0;
$enrolment['status'] = (isset($enrolment['suspend']) && !empty($enrolment['suspend'])) ?
ENROL_USER_SUSPENDED : ENROL_USER_ACTIVE;
$enrol->enrol_user($instance, $enrolment['userid'], $enrolment['roleid'],
$enrolment['timestart'], $enrolment['timeend'], $enrolment['status']);
}
$transaction->allow_commit();
}
/**
* Returns description of method result value.
*
* @return null
* @since Moodle 2.2
*/
public static function enrol_users_returns() {
return null;
}
/**
* Returns description of method parameters.
*
* @return external_function_parameters
*/
public static function unenrol_users_parameters() {
return new external_function_parameters(array(
'enrolments' => new external_multiple_structure(
new external_single_structure(
array(
'userid' => new external_value(PARAM_INT, 'The user that is going to be unenrolled'),
'courseid' => new external_value(PARAM_INT, 'The course to unenrol the user from'),
'roleid' => new external_value(PARAM_INT, 'The user role', VALUE_OPTIONAL),
)
)
)
));
}
/**
* Unenrolment of users.
*
* @param array $enrolments an array of course user and role ids
* @throws coding_exception
* @throws dml_transaction_exception
* @throws invalid_parameter_exception
* @throws moodle_exception
* @throws required_capability_exception
* @throws restricted_context_exception
*/
public static function unenrol_users($enrolments) {
global $CFG, $DB;
$params = self::validate_parameters(self::unenrol_users_parameters(), array('enrolments' => $enrolments));
require_once($CFG->libdir . '/enrollib.php');
$transaction = $DB->start_delegated_transaction(); // Rollback all enrolment if an error occurs.
$enrol = enrol_get_plugin('manual');
if (empty($enrol)) {
throw new moodle_exception('manualpluginnotinstalled', 'enrol_manual');
}
foreach ($params['enrolments'] as $enrolment) {
$context = context_course::instance($enrolment['courseid']);
self::validate_context($context);
require_capability('enrol/manual:unenrol', $context);
$instance = $DB->get_record('enrol', array('courseid' => $enrolment['courseid'], 'enrol' => 'manual'));
if (!$instance) {
throw new moodle_exception('wsnoinstance', 'enrol_manual', '', $enrolment);
}
$user = $DB->get_record('user', array('id' => $enrolment['userid']));
if (!$user) {
throw new invalid_parameter_exception('User id not exist: '.$enrolment['userid']);
}
if (!$enrol->allow_unenrol($instance)) {
throw new moodle_exception('wscannotunenrol', 'enrol_manual', '', $enrolment);
}
$enrol->unenrol_user($instance, $enrolment['userid']);
}
$transaction->allow_commit();
}
/**
* Returns description of method result value.
*
* @return null
*/
public static function unenrol_users_returns() {
return null;
}
}
+86
View File
@@ -0,0 +1,86 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'enrol_manual', language 'en'.
*
* @package enrol_manual
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['advanced'] = 'Advanced';
$string['alterstatus'] = 'Alter status';
$string['altertimeend'] = 'Alter end time';
$string['altertimestart'] = 'Alter start time';
$string['assignrole'] = 'Assign role';
$string['assignroles'] = 'Assign roles';
$string['browseusers'] = 'Browse users';
$string['browsecohorts'] = 'Browse cohorts';
$string['confirmbulkdeleteenrolment'] = 'Are you sure you want to delete these user enrolments?';
$string['defaultstart'] = 'Default enrolment start';
$string['defaultperiod'] = 'Default enrolment duration';
$string['defaultperiod_desc'] = 'Default length of time that the enrolment is valid. If set to zero, the enrolment duration will be unlimited by default.';
$string['defaultperiod_help'] = 'Default length of time that the enrolment is valid, starting with the moment the user is enrolled. If disabled, the enrolment duration will be unlimited by default.';
$string['deleteselectedusers'] = 'Delete selected user enrolments';
$string['editselectedusers'] = 'Edit selected user enrolments';
$string['enrolledincourserole'] = 'Enrolled in "{$a->course}" as "{$a->role}"';
$string['enrolusers'] = 'Enrol users';
$string['enroluserscohorts'] = 'Enrol selected users and cohorts';
$string['expiredaction'] = 'Enrolment expiry action';
$string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
$string['expirymessageenrollersubject'] = 'Enrolment expiry notification';
$string['expirymessageenrollerbody'] = 'Enrolment in the course \'{$a->course}\' will expire within the next {$a->threshold} for the following users:
{$a->users}
To extend their enrolment, go to {$a->extendurl}';
$string['expirymessageenrolledsubject'] = 'Enrolment expiry notification';
$string['expirymessageenrolledbody'] = 'Dear {$a->user},
This is a notification that your enrolment in the course \'{$a->course}\' is due to expire on {$a->timeend}.
If you need help, please contact {$a->enroller}.';
$string['managemanualenrolements'] = 'Manage manual enrolments';
$string['manual:config'] = 'Configure manual enrol instances';
$string['manual:enrol'] = 'Enrol users';
$string['manual:manage'] = 'Manage user enrolments';
$string['manual:unenrol'] = 'Unenrol users from the course';
$string['manual:unenrolself'] = 'Unenrol self from the course';
$string['messageprovider:expiry_notification'] = 'Manual enrolment expiry notifications';
$string['now'] = 'Now';
$string['pluginname'] = 'Manual enrolments';
$string['pluginname_desc'] = 'The manual enrolments plugin allows users to be enrolled manually via a link in the course administration settings, by a user with appropriate permissions such as a teacher. The plugin should normally be enabled, since certain other enrolment plugins, such as self enrolment, require it.';
$string['selection'] = 'Selection';
$string['selectusers'] = 'Select users';
$string['selectcohorts'] = 'Select cohorts';
$string['sendexpirynotificationstask'] = "Manual enrolment send expiry notifications task";
$string['status'] = 'Enable manual enrolments';
$string['status_desc'] = 'Allow course access of internally enrolled users. This should be kept enabled in most cases.';
$string['status_help'] = 'This setting determines whether users can be enrolled manually, via a link in the course administration settings, by a user with appropriate permissions such as a teacher.';
$string['statusenabled'] = 'Enabled';
$string['statusdisabled'] = 'Disabled';
$string['syncenrolmentstask'] = 'Synchronise manual enrolments task';
$string['unenrol'] = 'Unenrol user';
$string['unenrolselectedusers'] = 'Unenrol selected users';
$string['unenrolselfconfirm'] = 'Do you really want to unenrol yourself from course "{$a}"?';
$string['unenroluser'] = 'Do you really want to unenrol "{$a->user}" from course "{$a->course}"?';
$string['unenrolusers'] = 'Unenrol users';
$string['wscannotenrol'] = 'Plugin instance cannot manually enrol a user in the course id = {$a->courseid}';
$string['wsnoinstance'] = 'Manual enrolment plugin instance doesn\'t exist or is disabled for the course (id = {$a->courseid})';
$string['wsusercannotassign'] = 'You don\'t have the permission to assign this role ({$a->roleid}) to this user ({$a->userid}) in this course ({$a->courseid}).';
$string['manualpluginnotinstalled'] = 'The "Manual" plugin has not yet been installed';
$string['privacy:metadata'] = 'The Manual enrolments plugin does not store any personal data.';
+781
View File
@@ -0,0 +1,781 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual enrolment plugin main library file.
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
class enrol_manual_plugin extends enrol_plugin {
protected $lasternoller = null;
protected $lasternollerinstanceid = 0;
public function roles_protected() {
// Users may tweak the roles later.
return false;
}
public function allow_enrol(stdClass $instance) {
// Users with enrol cap may unenrol other users manually manually.
return true;
}
public function allow_unenrol(stdClass $instance) {
// Users with unenrol cap may unenrol other users manually manually.
return true;
}
public function allow_manage(stdClass $instance) {
// Users with manage cap may tweak period and status.
return true;
}
/**
* Returns link to manual enrol UI if exists.
* Does the access control tests automatically.
*
* @param stdClass $instance
* @return moodle_url
*/
public function get_manual_enrol_link($instance) {
$name = $this->get_name();
if ($instance->enrol !== $name) {
throw new coding_exception('invalid enrol instance!');
}
if (!enrol_is_enabled($name)) {
return NULL;
}
$context = context_course::instance($instance->courseid, MUST_EXIST);
if (!has_capability('enrol/manual:enrol', $context)) {
// Note: manage capability not used here because it is used for editing
// of existing enrolments which is not possible here.
return NULL;
}
return new moodle_url('/enrol/manual/manage.php', array('enrolid'=>$instance->id, 'id'=>$instance->courseid));
}
/**
* Return true if we can add a new instance to this course.
*
* @param int $courseid
* @return boolean
*/
public function can_add_instance($courseid) {
global $DB;
$context = context_course::instance($courseid, MUST_EXIST);
if (!has_capability('moodle/course:enrolconfig', $context) or !has_capability('enrol/manual:config', $context)) {
return false;
}
if ($DB->record_exists('enrol', array('courseid'=>$courseid, 'enrol'=>'manual'))) {
// Multiple instances not supported.
return false;
}
return true;
}
/**
* Returns edit icons for the page with list of instances.
* @param stdClass $instance
* @return array
*/
public function get_action_icons(stdClass $instance) {
global $OUTPUT;
$context = context_course::instance($instance->courseid);
$icons = array();
if (has_capability('enrol/manual:enrol', $context) or has_capability('enrol/manual:unenrol', $context)) {
$managelink = new moodle_url("/enrol/manual/manage.php", array('enrolid'=>$instance->id));
$icons[] = $OUTPUT->action_icon($managelink, new pix_icon('t/enrolusers', get_string('enrolusers', 'enrol_manual'), 'core', array('class'=>'iconsmall')));
}
$parenticons = parent::get_action_icons($instance);
$icons = array_merge($icons, $parenticons);
return $icons;
}
/**
* Add new instance of enrol plugin with default settings.
* @param stdClass $course
* @return int id of new instance, null if can not be created
*/
public function add_default_instance($course) {
$expirynotify = $this->get_config('expirynotify', 0);
$fields = array(
'status' => $this->get_config('status'),
'roleid' => $this->get_config('roleid', 0),
'enrolperiod' => $this->get_config('enrolperiod', 0),
'expirynotify' => $expirynotify,
'notifyall' => $expirynotify == 2 ? 1 : 0,
'expirythreshold' => $this->get_config('expirythreshold', 86400),
'customint1' => $this->get_config('sendcoursewelcomemessage'),
);
return $this->add_instance($course, $fields);
}
/**
* Add new instance of enrol plugin.
* @param stdClass $course
* @param array instance fields
* @return int id of new instance, null if can not be created
*/
public function add_instance($course, array $fields = NULL) {
global $DB;
if ($DB->record_exists('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'))) {
// only one instance allowed, sorry
return NULL;
}
return parent::add_instance($course, $fields);
}
/**
* Update instance of enrol plugin.
* @param stdClass $instance
* @param stdClass $data modified instance fields
* @return boolean
*/
public function update_instance($instance, $data) {
global $DB;
// Delete all other instances, leaving only one.
if ($instances = $DB->get_records('enrol', array('courseid' => $instance->courseid, 'enrol' => 'manual'), 'id ASC')) {
foreach ($instances as $anotherinstance) {
if ($anotherinstance->id != $instance->id) {
$this->delete_instance($anotherinstance);
}
}
}
$data->notifyall = $data->expirynotify == 2 ? 1 : 0;
return parent::update_instance($instance, $data);
}
/**
* Returns a button to manually enrol users through the manual enrolment plugin.
*
* By default the first manual enrolment plugin instance available in the course is used.
* If no manual enrolment instances exist within the course then false is returned.
*
* This function also adds a quickenrolment JS ui to the page so that users can be enrolled
* via AJAX.
*
* @param course_enrolment_manager $manager
* @return enrol_user_button
*/
public function get_manual_enrol_button(course_enrolment_manager $manager) {
global $CFG, $PAGE;
require_once($CFG->dirroot.'/cohort/lib.php');
static $called = false;
$instance = null;
foreach ($manager->get_enrolment_instances() as $tempinstance) {
if ($tempinstance->enrol == 'manual') {
if ($instance === null) {
$instance = $tempinstance;
}
}
}
if (empty($instance)) {
return false;
}
$link = $this->get_manual_enrol_link($instance);
if (!$link) {
return false;
}
$button = new enrol_user_button($link, get_string('enrolusers', 'enrol_manual'), 'get');
$button->class .= ' enrol_manual_plugin';
$button->type = single_button::BUTTON_PRIMARY;
$context = context_course::instance($instance->courseid);
$arguments = array('contextid' => $context->id);
if (!$called) {
$called = true;
// Calling the following more than once will cause unexpected results.
$PAGE->requires->js_call_amd('enrol_manual/quickenrolment', 'init', array($arguments));
}
return $button;
}
/**
* Sync all meta course links.
*
* @param progress_trace $trace
* @param int $courseid one course, empty mean all
* @return int 0 means ok, 1 means error, 2 means plugin disabled
*/
public function sync(progress_trace $trace, $courseid = null) {
global $DB;
if (!enrol_is_enabled('manual')) {
$trace->finished();
return 2;
}
// Unfortunately this may take a long time, execution can be interrupted safely here.
core_php_time_limit::raise();
raise_memory_limit(MEMORY_HUGE);
$trace->output('Verifying manual enrolment expiration...');
$params = array('now'=>time(), 'useractive'=>ENROL_USER_ACTIVE, 'courselevel'=>CONTEXT_COURSE);
$coursesql = "";
if ($courseid) {
$coursesql = "AND e.courseid = :courseid";
$params['courseid'] = $courseid;
}
// Deal with expired accounts.
$action = $this->get_config('expiredaction', ENROL_EXT_REMOVED_KEEP);
if ($action == ENROL_EXT_REMOVED_UNENROL) {
$instances = array();
$sql = "SELECT ue.*, e.courseid, c.id AS contextid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual')
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
$coursesql";
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $ue) {
if (empty($instances[$ue->enrolid])) {
$instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
}
$instance = $instances[$ue->enrolid];
// Always remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here.
role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true);
$this->unenrol_user($instance, $ue->userid);
$trace->output("unenrolling expired user $ue->userid from course $instance->courseid", 1);
}
$rs->close();
unset($instances);
} else if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES or $action == ENROL_EXT_REMOVED_SUSPEND) {
$instances = array();
$sql = "SELECT ue.*, e.courseid, c.id AS contextid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual')
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
AND ue.status = :useractive
$coursesql";
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $ue) {
if (empty($instances[$ue->enrolid])) {
$instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
}
$instance = $instances[$ue->enrolid];
if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
// Remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here.
role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true);
$this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
$trace->output("suspending expired user $ue->userid in course $instance->courseid, roles unassigned", 1);
} else {
$this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
$trace->output("suspending expired user $ue->userid in course $instance->courseid, roles kept", 1);
}
}
$rs->close();
unset($instances);
} else {
// ENROL_EXT_REMOVED_KEEP means no changes.
}
$trace->output('...manual enrolment updates finished.');
$trace->finished();
return 0;
}
/**
* Returns the user who is responsible for manual enrolments in given instance.
*
* Usually it is the first editing teacher - the person with "highest authority"
* as defined by sort_by_roleassignment_authority() having 'enrol/manual:manage'
* capability.
*
* @param int $instanceid enrolment instance id
* @return stdClass user record
*/
protected function get_enroller($instanceid) {
global $DB;
if ($this->lasternollerinstanceid == $instanceid and $this->lasternoller) {
return $this->lasternoller;
}
$instance = $DB->get_record('enrol', array('id'=>$instanceid, 'enrol'=>$this->get_name()), '*', MUST_EXIST);
$context = context_course::instance($instance->courseid);
if ($users = get_enrolled_users($context, 'enrol/manual:manage')) {
$users = sort_by_roleassignment_authority($users, $context);
$this->lasternoller = reset($users);
unset($users);
} else {
$this->lasternoller = parent::get_enroller($instanceid);
}
$this->lasternollerinstanceid = $instanceid;
return $this->lasternoller;
}
/**
* The manual plugin has several bulk operations that can be performed.
* @param course_enrolment_manager $manager
* @return array
*/
public function get_bulk_operations(course_enrolment_manager $manager) {
global $CFG;
require_once($CFG->dirroot.'/enrol/manual/locallib.php');
$context = $manager->get_context();
$bulkoperations = array();
if (has_capability("enrol/manual:manage", $context)) {
$bulkoperations['editselectedusers'] = new enrol_manual_editselectedusers_operation($manager, $this);
}
if (has_capability("enrol/manual:unenrol", $context)) {
$bulkoperations['deleteselectedusers'] = new enrol_manual_deleteselectedusers_operation($manager, $this);
}
return $bulkoperations;
}
/**
* Restore instance and map settings.
*
* @param restore_enrolments_structure_step $step
* @param stdClass $data
* @param stdClass $course
* @param int $oldid
*/
public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) {
global $DB;
// There is only I manual enrol instance allowed per course.
if ($instances = $DB->get_records('enrol', array('courseid'=>$data->courseid, 'enrol'=>'manual'), 'id')) {
$instance = reset($instances);
$instanceid = $instance->id;
} else {
$instanceid = $this->add_instance($course, (array)$data);
}
$step->set_mapping('enrol', $oldid, $instanceid);
}
/**
* Restore user enrolment.
*
* @param restore_enrolments_structure_step $step
* @param stdClass $data
* @param stdClass $instance
* @param int $oldinstancestatus
* @param int $userid
*/
public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) {
global $DB;
// Note: this is a bit tricky because other types may be converted to manual enrolments,
// and manual is restricted to one enrolment per user.
$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid));
$enrol = false;
if ($ue and $ue->status == ENROL_USER_ACTIVE) {
// We do not want to restrict current active enrolments, let's kind of merge the times only.
// This prevents some teacher lockouts too.
if ($data->status == ENROL_USER_ACTIVE) {
if ($data->timestart > $ue->timestart) {
$data->timestart = $ue->timestart;
$enrol = true;
}
if ($data->timeend == 0) {
if ($ue->timeend != 0) {
$enrol = true;
}
} else if ($ue->timeend == 0) {
$data->timeend = 0;
} else if ($data->timeend < $ue->timeend) {
$data->timeend = $ue->timeend;
$enrol = true;
}
}
} else {
if ($instance->status == ENROL_INSTANCE_ENABLED and $oldinstancestatus != ENROL_INSTANCE_ENABLED) {
// Make sure that user enrolments are not activated accidentally,
// we do it only here because it is not expected that enrolments are migrated to other plugins.
$data->status = ENROL_USER_SUSPENDED;
}
$enrol = true;
}
if ($enrol) {
$this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, $data->status);
}
}
/**
* Restore role assignment.
*
* @param stdClass $instance
* @param int $roleid
* @param int $userid
* @param int $contextid
*/
public function restore_role_assignment($instance, $roleid, $userid, $contextid) {
// This is necessary only because we may migrate other types to this instance,
// we do not use component in manual or self enrol.
role_assign($roleid, $userid, $contextid, '', 0);
}
/**
* Restore user group membership.
* @param stdClass $instance
* @param int $groupid
* @param int $userid
*/
public function restore_group_member($instance, $groupid, $userid) {
global $CFG;
require_once("$CFG->dirroot/group/lib.php");
// This might be called when forcing restore as manual enrolments.
groups_add_member($groupid, $userid);
}
/**
* Is it possible to delete enrol instance via standard UI?
*
* @param object $instance
* @return bool
*/
public function can_delete_instance($instance) {
$context = context_course::instance($instance->courseid);
return has_capability('enrol/manual:config', $context);
}
/**
* Is it possible to hide/show enrol instance via standard UI?
*
* @param stdClass $instance
* @return bool
*/
public function can_hide_show_instance($instance) {
$context = context_course::instance($instance->courseid);
return has_capability('enrol/manual:config', $context);
}
/**
* Enrol all not enrolled cohort members into course via enrol instance.
*
* @param stdClass $instance
* @param int $cohortid
* @param int $roleid optional role id
* @param int $timestart 0 means unknown
* @param int $timeend 0 means forever
* @param int $status default to ENROL_USER_ACTIVE for new enrolments, no change by default in updates
* @param bool $recovergrades restore grade history
* @return int The number of enrolled cohort users
*/
public function enrol_cohort(stdClass $instance, $cohortid, $roleid = null, $timestart = 0, $timeend = 0, $status = null, $recovergrades = null) {
global $DB;
$context = context_course::instance($instance->courseid);
list($esql, $params) = get_enrolled_sql($context);
$sql = "SELECT cm.userid FROM {cohort_members} cm LEFT JOIN ($esql) u ON u.id = cm.userid ".
"WHERE cm.cohortid = :cohortid AND u.id IS NULL";
$params['cohortid'] = $cohortid;
$members = $DB->get_fieldset_sql($sql, $params);
foreach ($members as $userid) {
$this->enrol_user($instance, $userid, $roleid, $timestart, $timeend, $status, $recovergrades);
}
return count($members);
}
/**
* We are a good plugin and don't invent our own UI/validation code path.
*
* @return boolean
*/
public function use_standard_editing_ui() {
return true;
}
/**
* Return an array of valid options for the status.
*
* @return array
*/
protected function get_status_options() {
$options = array(ENROL_INSTANCE_ENABLED => get_string('yes'),
ENROL_INSTANCE_DISABLED => get_string('no'));
return $options;
}
/**
* Return an array of valid options for the roleid.
*
* @param stdClass $instance
* @param context $context
* @return array
*/
protected function get_roleid_options($instance, $context) {
if ($instance->id) {
$roles = get_default_enrol_roles($context, $instance->roleid);
} else {
$roles = get_default_enrol_roles($context, $this->get_config('roleid'));
}
return $roles;
}
/**
* Return an array of valid options for the expirynotify.
*
* @return array
*/
protected function get_expirynotify_options() {
$options = array(
0 => get_string('no'),
1 => get_string('expirynotifyenroller', 'core_enrol'),
2 => get_string('expirynotifyall', 'core_enrol')
);
return $options;
}
/**
* Add elements to the edit instance form.
*
* @param stdClass $instance
* @param MoodleQuickForm $mform
* @param context $context
* @return bool
*/
public function edit_instance_form($instance, MoodleQuickForm $mform, $context) {
$options = $this->get_status_options();
$mform->addElement('select', 'status', get_string('status', 'enrol_manual'), $options);
$mform->addHelpButton('status', 'status', 'enrol_manual');
$mform->setDefault('status', $this->get_config('status'));
$roles = $this->get_roleid_options($instance, $context);
$mform->addElement('select', 'roleid', get_string('defaultrole', 'role'), $roles);
$mform->setDefault('roleid', $this->get_config('roleid'));
$options = array('optional' => true, 'defaultunit' => 86400);
$mform->addElement('duration', 'enrolperiod', get_string('defaultperiod', 'enrol_manual'), $options);
$mform->setDefault('enrolperiod', $this->get_config('enrolperiod'));
$mform->addHelpButton('enrolperiod', 'defaultperiod', 'enrol_manual');
$options = $this->get_expirynotify_options();
$mform->addElement('select', 'expirynotify', get_string('expirynotify', 'core_enrol'), $options);
$mform->addHelpButton('expirynotify', 'expirynotify', 'core_enrol');
$options = array('optional' => false, 'defaultunit' => 86400);
$mform->addElement('duration', 'expirythreshold', get_string('expirythreshold', 'core_enrol'), $options);
$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);
}
}
/**
* Perform custom validation of the data used to edit the instance.
*
* @param array $data array of ("fieldname"=>value) of submitted data
* @param array $files array of uploaded files "element_name"=>tmp_file_path
* @param object $instance The instance loaded from the DB
* @param context $context The context of the instance we are editing
* @return array of "element_name"=>"error_description" if there are errors,
* or an empty array if everything is OK.
* @return void
*/
public function edit_instance_validation($data, $files, $instance, $context) {
$errors = array();
if ($data['expirynotify'] > 0 and $data['expirythreshold'] < 86400) {
$errors['expirythreshold'] = get_string('errorthresholdlow', 'core_enrol');
}
$validstatus = array_keys($this->get_status_options());
$validroles = array_keys($this->get_roleid_options($instance, $context));
$validexpirynotify = array_keys($this->get_expirynotify_options());
$tovalidate = array(
'status' => $validstatus,
'roleid' => $validroles,
'enrolperiod' => PARAM_INT,
'expirynotify' => $validexpirynotify,
'expirythreshold' => PARAM_INT
);
$typeerrors = $this->validate_param_types($data, $tovalidate);
$errors = array_merge($errors, $typeerrors);
return $errors;
}
/**
* Check if enrolment plugin is supported in csv course upload.
*
* @return bool
*/
public function is_csv_upload_supported(): bool {
return true;
}
/**
* Finds matching instances for a given course.
*
* @param array $enrolmentdata enrolment data.
* @param int $courseid Course ID.
* @return stdClass|null Matching instance
*/
public function find_instance(array $enrolmentdata, int $courseid): ?stdClass {
$instances = enrol_get_instances($courseid, false);
$instance = null;
foreach ($instances as $i) {
if ($i->enrol == 'manual') {
// There can be only one manual enrol instance so find first available.
$instance = $i;
break;
}
}
return $instance;
}
/**
* Fill custom fields data for a given enrolment plugin.
*
* @param array $enrolmentdata enrolment data.
* @param int $courseid Course ID.
* @return array Updated enrolment data with custom fields info.
*/
public function fill_enrol_custom_fields(array $enrolmentdata, int $courseid): array {
return $enrolmentdata + [
'expirynotify' => 0,
'expirythreshold' => 0,
];
}
/**
* Returns defaults for new instances.
*
* @return array
*/
public function get_instance_defaults(): array {
$fields['customint1'] = $this->get_config('sendcoursewelcomemessage');
return $fields;
}
}
/**
* Serve the manual enrol users form as a fragment.
*
* @param array $args List of named arguments for the fragment loader.
* @return string
*/
function enrol_manual_output_fragment_enrol_users_form($args) {
$args = (object) $args;
$context = $args->context;
$o = '';
require_capability('enrol/manual:enrol', $context);
$mform = new enrol_manual_enrol_users_form(null, $args);
ob_start();
$mform->display();
$o .= ob_get_contents();
ob_end_clean();
return $o;
}
+513
View File
@@ -0,0 +1,513 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Auxiliary manual user enrolment lib, the main purpose is to lower memory requirements...
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/user/selector/lib.php');
require_once($CFG->dirroot . '/enrol/locallib.php');
/**
* Enrol candidates.
*/
class enrol_manual_potential_participant extends user_selector_base {
protected $enrolid;
public function __construct($name, $options) {
$this->enrolid = $options['enrolid'];
$options['includecustomfields'] = true;
parent::__construct($name, $options);
}
/**
* Candidate users
* @param string $search
* @return array
*/
public function find_users($search) {
global $DB;
// By default wherecondition retrieves all users except the deleted, not confirmed and guest.
list($wherecondition, $params) = $this->search_sql($search, 'u');
$params = array_merge($params, $this->userfieldsparams);
$params['enrolid'] = $this->enrolid;
$fields = 'SELECT u.id, ' . $this->userfieldsselects;
$countfields = 'SELECT COUNT(1)';
$sql = " FROM {user} u
LEFT JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)
$this->userfieldsjoin
WHERE $wherecondition
AND ue.id IS NULL";
list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext, $this->userfieldsmappings);
$order = ' ORDER BY ' . $sort;
if (!$this->is_validating()) {
$potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
if ($potentialmemberscount > $this->maxusersperpage) {
return $this->too_many_results($search, $potentialmemberscount);
}
}
$availableusers = $DB->get_records_sql($fields . $sql . $order, array_merge($params, $sortparams));
if (empty($availableusers)) {
return array();
}
if ($search) {
$groupname = get_string('enrolcandidatesmatching', 'enrol', $search);
} else {
$groupname = get_string('enrolcandidates', 'enrol');
}
return array($groupname => $availableusers);
}
protected function get_options() {
$options = parent::get_options();
$options['enrolid'] = $this->enrolid;
$options['file'] = 'enrol/manual/locallib.php';
return $options;
}
}
/**
* Enrolled users.
*/
class enrol_manual_current_participant extends user_selector_base {
protected $courseid;
protected $enrolid;
public function __construct($name, $options) {
$this->enrolid = $options['enrolid'];
$options['includecustomfields'] = true;
parent::__construct($name, $options);
}
/**
* Candidate users
* @param string $search
* @return array
*/
public function find_users($search) {
global $DB;
// By default wherecondition retrieves all users except the deleted, not confirmed and guest.
list($wherecondition, $params) = $this->search_sql($search, 'u');
$params = array_merge($params, $this->userfieldsparams);
$params['enrolid'] = $this->enrolid;
$fields = 'SELECT u.id, ' . $this->userfieldsselects;
$countfields = 'SELECT COUNT(1)';
$sql = " FROM {user} u
JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)
$this->userfieldsjoin
WHERE $wherecondition";
list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext, $this->userfieldsmappings);
$order = ' ORDER BY ' . $sort;
if (!$this->is_validating()) {
$potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
if ($potentialmemberscount > $this->maxusersperpage) {
return $this->too_many_results($search, $potentialmemberscount);
}
}
$availableusers = $DB->get_records_sql($fields . $sql . $order, array_merge($params, $sortparams));
if (empty($availableusers)) {
return array();
}
if ($search) {
$groupname = get_string('enrolledusersmatching', 'enrol', $search);
} else {
$groupname = get_string('enrolledusers', 'enrol');
}
return array($groupname => $availableusers);
}
protected function get_options() {
$options = parent::get_options();
$options['enrolid'] = $this->enrolid;
$options['file'] = 'enrol/manual/locallib.php';
return $options;
}
}
/**
* A bulk operation for the manual enrolment plugin to edit selected users.
*
* @copyright 2011 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_manual_editselectedusers_operation extends enrol_bulk_enrolment_operation {
/**
* Returns the title to display for this bulk operation.
*
* @return string
*/
public function get_title() {
return get_string('editselectedusers', 'enrol_manual');
}
/**
* Returns the identifier for this bulk operation. This is the key used when the plugin
* returns an array containing all of the bulk operations it supports.
*/
public function get_identifier() {
return 'editselectedusers';
}
/**
* Processes the bulk operation request for the given userids with the provided properties.
*
* @param course_enrolment_manager $manager
* @param array $userids
* @param stdClass $properties The data returned by the form.
*/
public function process(course_enrolment_manager $manager, array $users, stdClass $properties) {
global $DB, $USER;
if (!has_capability("enrol/manual:manage", $manager->get_context())) {
return false;
}
// Get all of the user enrolment id's.
$ueids = array();
$instances = array();
foreach ($users as $user) {
foreach ($user->enrolments as $enrolment) {
$ueids[] = $enrolment->id;
if (!array_key_exists($enrolment->id, $instances)) {
$instances[$enrolment->id] = $enrolment;
}
}
}
// Check that each instance is manageable by the current user.
foreach ($instances as $instance) {
if (!$this->plugin->allow_manage($instance)) {
return false;
}
}
// Collect the known properties.
$status = $properties->status;
$timestart = $properties->timestart;
$timeend = $properties->timeend;
list($ueidsql, $params) = $DB->get_in_or_equal($ueids, SQL_PARAMS_NAMED);
$updatesql = array();
if ($status == ENROL_USER_ACTIVE || $status == ENROL_USER_SUSPENDED) {
$updatesql[] = 'status = :status';
$params['status'] = (int)$status;
}
if (!empty($timestart)) {
$updatesql[] = 'timestart = :timestart';
$params['timestart'] = (int)$timestart;
}
if (!empty($timeend)) {
$updatesql[] = 'timeend = :timeend';
$params['timeend'] = (int)$timeend;
}
if (empty($updatesql)) {
return true;
}
// Update the modifierid.
$updatesql[] = 'modifierid = :modifierid';
$params['modifierid'] = (int)$USER->id;
// Update the time modified.
$updatesql[] = 'timemodified = :timemodified';
$params['timemodified'] = time();
// Build the SQL statement.
$updatesql = join(', ', $updatesql);
$sql = "UPDATE {user_enrolments}
SET $updatesql
WHERE id $ueidsql";
if ($DB->execute($sql, $params)) {
foreach ($users as $user) {
foreach ($user->enrolments as $enrolment) {
$enrolment->courseid = $enrolment->enrolmentinstance->courseid;
$enrolment->enrol = 'manual';
// Trigger event.
$event = \core\event\user_enrolment_updated::create(
array(
'objectid' => $enrolment->id,
'courseid' => $enrolment->courseid,
'context' => context_course::instance($enrolment->courseid),
'relateduserid' => $user->id,
'other' => array('enrol' => 'manual')
)
);
$event->trigger();
}
}
// Delete cached course contacts for this course because they may be affected.
cache::make('core', 'coursecontacts')->delete($manager->get_context()->instanceid);
return true;
}
return false;
}
/**
* Returns a enrol_bulk_enrolment_operation extension form to be used
* in collecting required information for this operation to be processed.
*
* @param string|moodle_url|null $defaultaction
* @param mixed $defaultcustomdata
* @return enrol_manual_editselectedusers_form
*/
public function get_form($defaultaction = null, $defaultcustomdata = null) {
global $CFG;
require_once($CFG->dirroot.'/enrol/manual/bulkchangeforms.php');
return new enrol_manual_editselectedusers_form($defaultaction, $defaultcustomdata);
}
}
/**
* A bulk operation for the manual enrolment plugin to delete selected users enrolments.
*
* @copyright 2011 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_manual_deleteselectedusers_operation extends enrol_bulk_enrolment_operation {
/**
* Returns the title to display for this bulk operation.
*
* @return string
*/
public function get_identifier() {
return 'deleteselectedusers';
}
/**
* Returns the identifier for this bulk operation. This is the key used when the plugin
* returns an array containing all of the bulk operations it supports.
*
* @return string
*/
public function get_title() {
return get_string('deleteselectedusers', 'enrol_manual');
}
/**
* Returns a enrol_bulk_enrolment_operation extension form to be used
* in collecting required information for this operation to be processed.
*
* @param string|moodle_url|null $defaultaction
* @param mixed $defaultcustomdata
* @return enrol_manual_editselectedusers_form
*/
public function get_form($defaultaction = null, $defaultcustomdata = null) {
global $CFG;
require_once($CFG->dirroot.'/enrol/manual/bulkchangeforms.php');
if (!array($defaultcustomdata)) {
$defaultcustomdata = array();
}
$defaultcustomdata['title'] = $this->get_title();
$defaultcustomdata['message'] = get_string('confirmbulkdeleteenrolment', 'enrol_manual');
$defaultcustomdata['button'] = get_string('unenrolusers', 'enrol_manual');
return new enrol_manual_deleteselectedusers_form($defaultaction, $defaultcustomdata);
}
/**
* Processes the bulk operation request for the given userids with the provided properties.
*
* @global moodle_database $DB
* @param course_enrolment_manager $manager
* @param array $userids
* @param stdClass $properties The data returned by the form.
*/
public function process(course_enrolment_manager $manager, array $users, stdClass $properties) {
if (!has_capability("enrol/manual:unenrol", $manager->get_context())) {
return false;
}
$counter = 0;
foreach ($users as $user) {
foreach ($user->enrolments as $enrolment) {
$plugin = $enrolment->enrolmentplugin;
$instance = $enrolment->enrolmentinstance;
if ($plugin->allow_unenrol_user($instance, $enrolment)) {
$plugin->unenrol_user($instance, $user->id);
$counter++;
}
}
}
// Display a notification message after the bulk user unenrollment.
if ($counter > 0) {
\core\notification::info(get_string('totalunenrolledusers', 'enrol', $counter));
}
return true;
}
}
/**
* Migrates all enrolments of the given plugin to enrol_manual plugin,
* this is used for example during plugin uninstallation.
*
* NOTE: this function does not trigger role and enrolment related events.
*
* @param string $enrol The enrolment method.
*/
function enrol_manual_migrate_plugin_enrolments($enrol) {
global $DB;
if ($enrol === 'manual') {
// We can not migrate to self.
return;
}
$manualplugin = enrol_get_plugin('manual');
$params = array('enrol'=>$enrol);
$sql = "SELECT e.id, e.courseid, e.status, MIN(me.id) AS mid, COUNT(ue.id) AS cu
FROM {enrol} e
JOIN {user_enrolments} ue ON (ue.enrolid = e.id)
JOIN {course} c ON (c.id = e.courseid)
LEFT JOIN {enrol} me ON (me.courseid = e.courseid AND me.enrol='manual')
WHERE e.enrol = :enrol
GROUP BY e.id, e.courseid, e.status
ORDER BY e.id";
$rs = $DB->get_recordset_sql($sql, $params);
foreach($rs as $e) {
$minstance = false;
if (!$e->mid) {
// Manual instance does not exist yet, add a new one.
$course = $DB->get_record('course', array('id'=>$e->courseid), '*', MUST_EXIST);
if ($minstance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'))) {
// Already created by previous iteration.
$e->mid = $minstance->id;
} else if ($e->mid = $manualplugin->add_default_instance($course)) {
$minstance = $DB->get_record('enrol', array('id'=>$e->mid));
if ($e->status != ENROL_INSTANCE_ENABLED) {
$DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$e->mid));
$minstance->status = ENROL_INSTANCE_DISABLED;
}
}
} else {
$minstance = $DB->get_record('enrol', array('id'=>$e->mid));
}
if (!$minstance) {
// This should never happen unless adding of default instance fails unexpectedly.
debugging('Failed to find manual enrolment instance', DEBUG_DEVELOPER);
continue;
}
// First delete potential role duplicates.
$params = array('id'=>$e->id, 'component'=>'enrol_'.$enrol, 'empty'=>'');
$sql = "SELECT ra.id
FROM {role_assignments} ra
JOIN {role_assignments} mra ON (mra.contextid = ra.contextid AND mra.userid = ra.userid AND mra.roleid = ra.roleid AND mra.component = :empty AND mra.itemid = 0)
WHERE ra.component = :component AND ra.itemid = :id";
$ras = $DB->get_records_sql($sql, $params);
$ras = array_keys($ras);
$DB->delete_records_list('role_assignments', 'id', $ras);
unset($ras);
// Migrate roles.
$sql = "UPDATE {role_assignments}
SET itemid = 0, component = :empty
WHERE itemid = :id AND component = :component";
$params = array('empty'=>'', 'id'=>$e->id, 'component'=>'enrol_'.$enrol);
$DB->execute($sql, $params);
// Delete potential enrol duplicates.
$params = array('id'=>$e->id, 'mid'=>$e->mid);
$sql = "SELECT ue.id
FROM {user_enrolments} ue
JOIN {user_enrolments} mue ON (mue.userid = ue.userid AND mue.enrolid = :mid)
WHERE ue.enrolid = :id";
$ues = $DB->get_records_sql($sql, $params);
$ues = array_keys($ues);
$DB->delete_records_list('user_enrolments', 'id', $ues);
unset($ues);
// Migrate to manual enrol instance.
$params = array('id'=>$e->id, 'mid'=>$e->mid);
if ($e->status != ENROL_INSTANCE_ENABLED and $minstance->status == ENROL_INSTANCE_ENABLED) {
$status = ", status = :disabled";
$params['disabled'] = ENROL_USER_SUSPENDED;
} else {
$status = "";
}
$sql = "UPDATE {user_enrolments}
SET enrolid = :mid $status
WHERE enrolid = :id";
$DB->execute($sql, $params);
}
$rs->close();
}
/**
* Gets an array of the cohorts that can be enrolled in this course.
*
* @param int $enrolid
* @param string $search
* @param int $page Defaults to 0
* @param int $perpage Defaults to 25
* @param int $addedenrollment
* @return array Array(totalcohorts => int, cohorts => array)
*/
function enrol_manual_get_potential_cohorts($context, $enrolid, $search = '', $page = 0, $perpage = 25, $addedenrollment = 0) {
global $CFG;
require_once($CFG->dirroot . '/cohort/lib.php');
$allcohorts = cohort_get_available_cohorts($context, COHORT_WITH_NOTENROLLED_MEMBERS_ONLY, 0, 0, $search);
$totalcohorts = count($allcohorts);
$cohorts = array();
$cnt = 0;
foreach ($allcohorts as $c) {
if ($cnt >= $page * $perpage && (!$perpage || $cnt < ($page+1)*$perpage)) {
$cohorts[] = (object)array(
'id' => $c->id,
'name' => format_string($c->name, true, array('context' => $c->contextid)),
'cnt' => $c->memberscnt - $c->enrolledcnt
);
}
$cnt++;
}
return array('totalcohorts' => $totalcohorts, 'cohorts' => $cohorts);
}
+224
View File
@@ -0,0 +1,224 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual user enrolment UI.
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require('../../config.php');
require_once($CFG->dirroot.'/enrol/manual/locallib.php');
$enrolid = required_param('enrolid', PARAM_INT);
$roleid = optional_param('roleid', -1, PARAM_INT);
$extendperiod = optional_param('extendperiod', 0, PARAM_INT);
$extendbase = optional_param('extendbase', 0, PARAM_INT);
$timeend = optional_param_array('timeend', [], PARAM_INT);
$instance = $DB->get_record('enrol', array('id'=>$enrolid, 'enrol'=>'manual'), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
$context = context_course::instance($course->id, MUST_EXIST);
require_login($course);
$canenrol = has_capability('enrol/manual:enrol', $context);
$canunenrol = has_capability('enrol/manual:unenrol', $context);
// Note: manage capability not used here because it is used for editing
// of existing enrolments which is not possible here.
if (!$canenrol and !$canunenrol) {
// No need to invent new error strings here...
require_capability('enrol/manual:enrol', $context);
require_capability('enrol/manual:unenrol', $context);
}
if ($roleid < 0) {
$roleid = $instance->roleid;
}
$roles = get_assignable_roles($context);
$roles = array('0'=>get_string('none')) + $roles;
if (!isset($roles[$roleid])) {
// Weird - security always first!
$roleid = 0;
}
if (!$enrol_manual = enrol_get_plugin('manual')) {
throw new coding_exception('Can not instantiate enrol_manual');
}
$url = new moodle_url('/enrol/manual/manage.php', ['enrolid' => $instance->id]);
$title = get_string('managemanualenrolements', 'enrol_manual');
$PAGE->set_url($url);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($title);
$PAGE->set_heading($course->fullname);
navigation_node::override_active_url(new moodle_url('/enrol/instances.php', ['id' => $course->id]));
$PAGE->navbar->add($title, $url);
// Create the user selector objects.
$options = array('enrolid' => $enrolid, 'accesscontext' => $context);
$potentialuserselector = new enrol_manual_potential_participant('addselect', $options);
$currentuserselector = new enrol_manual_current_participant('removeselect', $options);
// Build the list of options for the enrolment period dropdown.
$unlimitedperiod = get_string('unlimited');
$periodmenu = array();
for ($i=1; $i<=365; $i++) {
$seconds = $i * 86400;
$periodmenu[$seconds] = get_string('numdays', '', $i);
}
// Work out the apropriate default settings.
if ($extendperiod) {
$defaultperiod = $extendperiod;
} else {
$defaultperiod = $instance->enrolperiod;
}
if ($instance->enrolperiod > 0 && !isset($periodmenu[$instance->enrolperiod])) {
$periodmenu[$instance->enrolperiod] = format_time($instance->enrolperiod);
}
if (empty($extendbase)) {
if (!$extendbase = get_config('enrol_manual', 'enrolstart')) {
// Default to now if there is no system setting.
$extendbase = 4;
}
}
// Build the list of options for the starting from dropdown.
$now = time();
$today = make_timestamp(date('Y', $now), date('m', $now), date('d', $now), 0, 0, 0);
$dateformat = get_string('strftimedatefullshort');
// Enrolment start.
$basemenu = array();
if ($course->startdate > 0) {
$basemenu[2] = get_string('coursestart') . ' (' . userdate($course->startdate, $dateformat) . ')';
}
$basemenu[3] = get_string('today') . ' (' . userdate($today, $dateformat) . ')';
$basemenu[4] = get_string('now', 'enrol_manual') . ' (' . userdate($now, get_string('strftimedatetimeshort')) . ')';
// Process add and removes.
if ($canenrol && optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
$userstoassign = $potentialuserselector->get_selected_users();
if (!empty($userstoassign)) {
foreach($userstoassign as $adduser) {
switch($extendbase) {
case 2:
$timestart = $course->startdate;
break;
case 4:
// We mimic get_enrolled_sql round(time(), -2) but always floor as we want users to always access their
// courses once they are enrolled.
$timestart = intval(substr($now, 0, 8) . '00') - 1;
break;
case 3:
default:
$timestart = $today;
break;
}
if ($timeend) {
$timeend = make_timestamp($timeend['year'], $timeend['month'], $timeend['day'], $timeend['hour'],
$timeend['minute']);
} else if ($extendperiod <= 0) {
$timeend = 0;
} else {
$timeend = $timestart + $extendperiod;
}
$enrol_manual->enrol_user($instance, $adduser->id, $roleid, $timestart, $timeend);
}
$potentialuserselector->invalidate_selected_users();
$currentuserselector->invalidate_selected_users();
//TODO: log
}
}
// Process incoming role unassignments.
if ($canunenrol && optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
$userstounassign = $currentuserselector->get_selected_users();
if (!empty($userstounassign)) {
foreach($userstounassign as $removeuser) {
$enrol_manual->unenrol_user($instance, $removeuser->id);
}
$potentialuserselector->invalidate_selected_users();
$currentuserselector->invalidate_selected_users();
//TODO: log
}
}
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
$addenabled = $canenrol ? '' : 'disabled="disabled"';
$removeenabled = $canunenrol ? '' : 'disabled="disabled"';
?>
<form id="assignform" method="post" action="<?php echo $PAGE->url ?>"><div>
<input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
<table summary="" class="roleassigntable generaltable generalbox boxaligncenter" cellspacing="0">
<tr>
<td id="existingcell">
<p><label for="removeselect"><?php print_string('enrolledusers', 'enrol'); ?></label></p>
<?php $currentuserselector->display() ?>
</td>
<td id="buttonscell">
<div id="addcontrols">
<input class="btn btn-secondary" name="add" <?php echo $addenabled; ?> id="add" type="submit"
value="<?php echo $OUTPUT->larrow() . '&nbsp;' . get_string('add'); ?>"
title="<?php print_string('add'); ?>" /><br />
<div class="enroloptions">
<p><label for="menuroleid"><?php print_string('assignrole', 'enrol_manual') ?></label><br />
<?php echo html_writer::select($roles, 'roleid', $roleid, false); ?></p>
<p><label for="menuextendperiod"><?php print_string('enrolperiod', 'enrol') ?></label><br />
<?php echo html_writer::select($periodmenu, 'extendperiod', $defaultperiod, $unlimitedperiod); ?></p>
<p><label for="menuextendbase"><?php print_string('startingfrom') ?></label><br />
<?php echo html_writer::select($basemenu, 'extendbase', $extendbase, false); ?></p>
</div>
</div>
<div id="removecontrols">
<input class="btn btn-secondary" name="remove" id="remove" <?php echo $removeenabled; ?> type="submit"
value="<?php echo get_string('remove') . '&nbsp;' . $OUTPUT->rarrow(); ?>"
title="<?php print_string('remove'); ?>" />
</div>
</td>
<td id="potentialcell">
<p><label for="addselect"><?php print_string('enrolcandidates', 'enrol'); ?></label></p>
<?php $potentialuserselector->display() ?>
</td>
</tr>
</table>
</div></form>
<?php
echo $OUTPUT->footer();
+100
View File
@@ -0,0 +1,100 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual enrolment plugin settings and presets.
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
if ($ADMIN->fulltree) {
//--- general settings -----------------------------------------------------------------------------------
$settings->add(new admin_setting_heading('enrol_manual_settings', '', get_string('pluginname_desc', 'enrol_manual')));
// Note: let's reuse the ext sync constants and strings here, internally it is very similar,
// it describes what should happend when users are not supposed to be enerolled any more.
$options = array(
ENROL_EXT_REMOVED_KEEP => get_string('extremovedkeep', 'enrol'),
ENROL_EXT_REMOVED_SUSPEND => get_string('extremovedsuspend', 'enrol'),
ENROL_EXT_REMOVED_SUSPENDNOROLES => get_string('extremovedsuspendnoroles', 'enrol'),
ENROL_EXT_REMOVED_UNENROL => get_string('extremovedunenrol', 'enrol'),
);
$settings->add(new admin_setting_configselect('enrol_manual/expiredaction', get_string('expiredaction', 'enrol_manual'), get_string('expiredaction_help', 'enrol_manual'), ENROL_EXT_REMOVED_KEEP, $options));
$options = array();
for ($i=0; $i<24; $i++) {
$options[$i] = $i;
}
$settings->add(new admin_setting_configselect('enrol_manual/expirynotifyhour', get_string('expirynotifyhour', 'core_enrol'), '', 6, $options));
//--- enrol instance defaults ----------------------------------------------------------------------------
$settings->add(new admin_setting_heading('enrol_manual_defaults',
get_string('enrolinstancedefaults', 'admin'), get_string('enrolinstancedefaults_desc', 'admin')));
$settings->add(new admin_setting_configcheckbox('enrol_manual/defaultenrol',
get_string('defaultenrol', 'enrol'), get_string('defaultenrol_desc', 'enrol'), 1));
$options = array(ENROL_INSTANCE_ENABLED => get_string('yes'),
ENROL_INSTANCE_DISABLED => get_string('no'));
$settings->add(new admin_setting_configselect('enrol_manual/status',
get_string('status', 'enrol_manual'), get_string('status_desc', 'enrol_manual'), ENROL_INSTANCE_ENABLED, $options));
if (!during_initial_install()) {
$options = get_default_enrol_roles(context_system::instance());
$student = get_archetype_roles('student');
$student = reset($student);
$settings->add(new admin_setting_configselect('enrol_manual/roleid',
get_string('defaultrole', 'role'), '', $student->id ?? null, $options));
}
$options = array(2 => get_string('coursestart'), 3 => get_string('today'), 4 => get_string('now', 'enrol_manual'));
$settings->add(
new admin_setting_configselect('enrol_manual/enrolstart', get_string('defaultstart', 'enrol_manual'), '', 4, $options)
);
$settings->add(new admin_setting_configduration('enrol_manual/enrolperiod',
get_string('defaultperiod', 'enrol_manual'), get_string('defaultperiod_desc', 'enrol_manual'), 0));
$options = array(0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol'));
$settings->add(new admin_setting_configselect('enrol_manual/expirynotify',
get_string('expirynotify', 'core_enrol'), get_string('expirynotify_help', 'core_enrol'), 0, $options));
$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(),
),
);
}
@@ -0,0 +1,57 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template enrol_manual/form-user-selector-suggestion
Moodle template for the list of valid options in an autocomplate form element.
Classes required for JS:
* none
Data attributes required for JS:
* none
Context variables required for this template:
* profileimageurlsmall Url to a small profile image.
* profileimageurl Url to a profile image.
* fullname Users full name
* hasidentity boolean to say if there are identity fields to show
* identity concatenated list of identity fields.
* id user id field
* email user email field
* idnumber user idnumber field
* phone1 user phone1 field
* phone2 user phone2 field
* department user department field
* institution user institution field
Example context (json):
{ "id": "1",
"fullname": "Admin",
"hasidentity": true,
"identity": "Admin User, 0144114141",
"profileimageurl": "invalid url",
"profileimageurlsmall": "invalid url"
}
}}
<span>
<img height="12" src="{{profileimageurlsmall}}" alt="">
<span>{{fullname}}</span>
{{#hasidentity}}
<span><small>{{identity}}</small></span>
{{/hasidentity}}
</span>
+95
View File
@@ -0,0 +1,95 @@
@enrol @enrol_manual
Feature: A teacher can manage manually enrolled users in their course
In order to manage manually enrolled students in my course
As a teacher
I can manually add and remove users in my course
Background:
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | fruit | Fruit |
And the following "users" exist:
| username | firstname | middlename | lastname | email | profile_field_fruit |
| teacher | Teacher | | User | teacher@example.com | |
| user1 | First | Alice | User | first@example.com | Apple |
| user2 | Second | Bob | User | second@example.com | Banana |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher | C1 | editingteacher |
@javascript
Scenario Outline: Manually enrolling users should observe alternative fullname format
Given the following config values are set as admin:
| alternativefullnameformat | firstname middlename lastname |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:viewfullnames | <permission> | editingteacher | Course | C1 |
When I am on the "Course 1" "enrolment methods" page logged in as "teacher"
And I click on "Enrol users" "link" in the "Manual enrolments" "table_row"
And I set the field "addselect_searchtext" to "First"
And I wait "1" seconds
And I set the field "Not enrolled users" to "<expectedfullname> (first@example.com)"
And I press "Add"
Then the "Enrolled users" select box should contain "<expectedfullname> (first@example.com)"
Examples:
| permission | expectedfullname |
| Allow | First Alice User |
| Prohibit | First User |
@javascript
Scenario Outline: Manually unenrolling users should observe alternative fullname format
Given the following config values are set as admin:
| alternativefullnameformat | firstname middlename lastname |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:viewfullnames | <permission> | editingteacher | Course | C1 |
And the following "course enrolments" exist:
| user | course | role |
| user1 | C1 | student |
| user2 | C1 | student |
When I am on the "Course 1" "enrolment methods" page logged in as "teacher"
And I click on "Enrol users" "link" in the "Manual enrolments" "table_row"
And I set the field "removeselect_searchtext" to "First"
And I wait "1" seconds
And I set the field "Enrolled users" to "<expectedfullname> (first@example.com)"
And I press "Remove"
Then the "Not enrolled users" select box should contain "<expectedfullname> (first@example.com)"
Examples:
| permission | expectedfullname |
| Allow | First Alice User |
| Prohibit | First User |
@javascript
Scenario: Manually enrol users in course using custom user profile fields
Given the following config values are set as admin:
| showuseridentity | email,profile_field_fruit |
When I am on the "Course 1" "enrolment methods" page logged in as "teacher"
And I click on "Enrol users" "link" in the "Manual enrolments" "table_row"
Then the "Not enrolled users" select box should contain "Second User (second@example.com\, Banana)"
And I set the field "addselect_searchtext" to "Apple"
And I wait "1" seconds
And the "Not enrolled users" select box should not contain "Second User (second@example.com\, Banana)"
And I set the field "Not enrolled users" to "First User (first@example.com\, Apple)"
And I press "Add"
And the "Enrolled users" select box should contain "First User (first@example.com\, Apple)"
@javascript
Scenario: Manually unenrol users in course using custom user profile fields
Given the following config values are set as admin:
| showuseridentity | email,profile_field_fruit |
And the following "course enrolments" exist:
| user | course | role |
| user1 | C1 | student |
| user2 | C1 | student |
When I am on the "Course 1" "enrolment methods" page logged in as "teacher"
And I click on "Enrol users" "link" in the "Manual enrolments" "table_row"
Then the "Enrolled users" select box should contain "Second User (second@example.com\, Banana)"
And I set the field "removeselect_searchtext" to "Apple"
And I wait "1" seconds
And the "Enrolled users" select box should not contain "Second User (second@example.com\, Banana)"
And I set the field "Enrolled users" to "First User (first@example.com\, Apple)"
And I press "Remove"
And the "Not enrolled users" select box should contain "First User (first@example.com\, Apple)"
@@ -0,0 +1,258 @@
@enrol @enrol_manual
Feature: Teacher can search and enrol users one by one into the course
In order to quickly enrol particular students into my course
As a teacher
I can search for the students and enrol them into the course
Background:
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | customid | Custom user id |
And the following "users" exist:
| username | firstname | lastname | email | profile_field_customid |
| teacher001 | Teacher | 001 | teacher001@example.com | |
| student001 | Student | 001 | student001@example.com | Q994 |
| student002 | Student | 002 | student002@example.com | Q008 |
| student003 | Student | 003 | student003@example.com | Z442 |
| student004 | Student | 004 | student004@example.com | |
| student005 | Student | 005 | student005@example.com | |
| student006 | Student | 006 | student006@example.com | |
| student007 | Student | 007 | student007@example.com | |
| student008 | Student | 008 | student008@example.com | |
| student009 | Student | 009 | student009@example.com | |
| student010 | Student | 010 | student010@example.com | |
| student011 | Student | 011 | student011@example.com | |
| student012 | Student | 012 | student012@example.com | |
| student013 | Student | 013 | student013@example.com | |
| student014 | Student | 014 | student014@example.com | |
| student015 | Student | 015 | student015@example.com | |
| student016 | Student | 016 | student016@example.com | |
| student017 | Student | 017 | student017@example.com | |
| student018 | Student | 018 | student018@example.com | |
| student019 | Student | 019 | student019@example.com | |
| student020 | Student | 020 | student020@example.com | |
| student021 | Student | 021 | student021@example.com | |
| student022 | Student | 022 | student022@example.com | |
| student023 | Student | 023 | student023@example.com | |
| student024 | Student | 024 | student024@example.com | |
| student025 | Student | 025 | student025@example.com | |
| student026 | Student | 026 | student026@example.com | |
| student027 | Student | 027 | student027@example.com | |
| student028 | Student | 028 | student028@example.com | |
| student029 | Student | 029 | student029@example.com | |
| student030 | Student | 030 | student030@example.com | |
| student031 | Student | 031 | student031@example.com | |
| student032 | Student | 032 | student032@example.com | |
| student033 | Student | 033 | student033@example.com | |
| student034 | Student | 034 | student034@example.com | |
| student035 | Student | 035 | student035@example.com | |
| student036 | Student | 036 | student036@example.com | |
| student037 | Student | 037 | student037@example.com | |
| student038 | Student | 038 | student038@example.com | |
| student039 | Student | 039 | student039@example.com | |
| student040 | Student | 040 | student040@example.com | |
| student041 | Student | 041 | student041@example.com | |
| student042 | Student | 042 | student042@example.com | |
| student043 | Student | 043 | student043@example.com | |
| student044 | Student | 044 | student044@example.com | |
| student045 | Student | 045 | student045@example.com | |
| student046 | Student | 046 | student046@example.com | |
| student047 | Student | 047 | student047@example.com | |
| student048 | Student | 048 | student048@example.com | |
| student049 | Student | 049 | student049@example.com | |
| student050 | Student | 050 | student050@example.com | |
| student051 | Student | 051 | student051@example.com | |
| student052 | Student | 052 | student052@example.com | |
| student053 | Student | 053 | student053@example.com | |
| student054 | Student | 054 | student054@example.com | |
| student055 | Student | 055 | student055@example.com | |
| student056 | Student | 056 | student056@example.com | |
| student057 | Student | 057 | student057@example.com | |
| student058 | Student | 058 | student058@example.com | |
| student059 | Student | 059 | student059@example.com | |
| student060 | Student | 060 | student060@example.com | |
| student061 | Student | 061 | student061@example.com | |
| student062 | Student | 062 | student062@example.com | |
| student063 | Student | 063 | student063@example.com | |
| student064 | Student | 064 | student064@example.com | |
| student065 | Student | 065 | student065@example.com | |
| student066 | Student | 066 | student066@example.com | |
| student067 | Student | 067 | student067@example.com | |
| student068 | Student | 068 | student068@example.com | |
| student069 | Student | 069 | student069@example.com | |
| student070 | Student | 070 | student070@example.com | |
| student071 | Student | 071 | student071@example.com | |
| student072 | Student | 072 | student072@example.com | |
| student073 | Student | 073 | student073@example.com | |
| student074 | Student | 074 | student074@example.com | |
| student075 | Student | 075 | student075@example.com | |
| student076 | Student | 076 | student076@example.com | |
| student077 | Student | 077 | student077@example.com | |
| student078 | Student | 078 | student078@example.com | |
| student079 | Student | 079 | student079@example.com | |
| student080 | Student | 080 | student080@example.com | |
| student081 | Student | 081 | student081@example.com | |
| student082 | Student | 082 | student082@example.com | |
| student083 | Student | 083 | student083@example.com | |
| student084 | Student | 084 | student084@example.com | |
| student085 | Student | 085 | student085@example.com | |
| student086 | Student | 086 | student086@example.com | |
| student087 | Student | 087 | student087@example.com | |
| student088 | Student | 088 | student088@example.com | |
| student089 | Student | 089 | student089@example.com | |
| student090 | Student | 090 | student090@example.com | |
| student091 | Student | 091 | student091@example.com | |
| student092 | Student | 092 | student092@example.com | |
| student093 | Student | 093 | student093@example.com | |
| student094 | Student | 094 | student094@example.com | |
| student095 | Student | 095 | student095@example.com | |
| student096 | Student | 096 | student096@example.com | |
| student097 | Student | 097 | student097@example.com | |
| student098 | Student | 098 | student098@example.com | |
| student099 | Student | 099 | student099@example.com | |
And the following "courses" exist:
| fullname | shortname | format | startdate |
| Course 001 | C001 | weeks | ##1 month ago## |
And the following "course enrolments" exist:
| user | course | role | timestart |
| teacher001 | C001 | editingteacher | ##1 month ago## |
And I log in as "teacher001"
And I am on "Course 001" course homepage
@javascript
Scenario: Teacher can search and enrol one particular student
Given I navigate to course participants
And I press "Enrol users"
When I set the field "Select users" to "student001"
And I should see "Student 001"
And I click on "Enrol users" "button" in the "Enrol users" "dialogue"
Then I should see "Active" in the "Student 001" "table_row"
And I should see "1 enrolled users"
@javascript
Scenario: Searching for a non-existing user
Given I navigate to course participants
And I press "Enrol users"
And I click on "Select users" "field"
And I type "qwertyuiop"
Then I should see "No suggestions"
@javascript
Scenario: If there are less than 100 matching users, all are displayed for selection
Given I navigate to course participants
And I press "Enrol users"
When I click on "Select users" "field"
And I type "example.com"
Then "Student 099" "autocomplete_suggestions" should exist
@javascript
Scenario: If there are more than 100 matching users, inform there are too many.
Given the following "users" exist:
| username | firstname | lastname | email |
| student100 | Student | 100 | student100@example.com |
| student101 | Student | 101 | student101@example.com |
And I navigate to course participants
And I press "Enrol users"
When I click on "Select users" "field"
And I type "example.com"
Then I should see "Too many users (>100) to show"
@javascript
Scenario: Changing the Maximum users per page setting affects the enrolment pop-up.
Given the following config values are set as admin:
| maxusersperpage | 5 |
And I navigate to course participants
And I press "Enrol users"
When I click on "Select users" "field"
And I type "student00"
Then I should see "Too many users (>5) to show"
@javascript
Scenario: Change the Show user identity setting affects the enrolment pop-up.
Given I log out
When I log in as "admin"
Then the following "users" exist:
| username | firstname | lastname | email | phone1 | phone2 | department | institution | city | country |
| student100 | Student | 100 | student100@example.com | 1234567892 | 1234567893 | ABC1 | ABC2 | CITY1 | GB |
And the following config values are set as admin:
| showuseridentity | idnumber,email,city,country,phone1,phone2,department,institution |
When I am on "Course 001" course homepage
Then I navigate to course participants
And I press "Enrol users"
And I click on "Select users" "field"
And I type "student100@example.com"
Then I should see "student100@example.com, CITY1, GB, 1234567892, 1234567893, ABC1, ABC2"
# Remove identity field in setting User policies
And the following config values are set as admin:
| showuseridentity | idnumber,email,phone1,phone2,department,institution |
And I am on "Course 001" course homepage
And I navigate to course participants
And I press "Enrol users"
And I click on "Select users" "field"
And I type "student100@example.com"
And I should see "student100@example.com, 1234567892, 1234567893, ABC1, ABC2"
@javascript
Scenario: Custom user profile fields work for search and display, if user has permission
Given the following config values are set as admin:
| showuseridentity | email,profile_field_customid |
And I navigate to course participants
And I press "Enrol users"
When I set the field "Select users" to "Q994"
Then I should see "student001@example.com, Q994"
And I click on "Cancel" "button" in the "Enrol users" "dialogue"
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:viewuseridentity | Prevent | editingteacher | Course | C001 |
And I press "Enrol users"
# Do this by keyboard because the 'I set the field' step doesn't let you set it to a missing value.
And I press tab
And I press tab
And I press tab
And I type "Q994"
And I should see "No suggestions"
# The following tests are commented out as a result of MDL-66339.
# @javascript
# Scenario: Enrol user from participants page
# Given I navigate to course participants
# # Enrol user to course
# And I press "Enrol users"
# And I set the field "Select users" to "example.com"
# And I expand the "Select users" autocomplete
# When I click on "Student 099" item in the autocomplete list
# Then I should see "Student 099" in the list of options for the "Select users" autocomplete
# And I click on "Show more" "button"
# # Fill data to input duration
# And "input[name='timeend[enabled]'][checked=checked]" "css_element" should not exist
# And the "Enrolment duration" "select" should be enabled
# And I set the field "duration" to "2"
# # Fill data to input end time
# And I set the field "Starting from" to "2"
# And I set the field "timeend[enabled]" to "1"
# And I set the field "timeend[day]" to "10"
# And the "Enrolment duration" "select" should be disabled
# And I click on "Enrol users" "button" in the "Enrol users" "dialogue"
# And I am on "Course 001" course homepage
# And I navigate to course participants
# And I should see "Student 099" in the "participants" "table"
# And I click on "Edit enrolment" "icon" in the "Student 099" "table_row"
# And the field "timeend[day]" matches value "10"
#
# @javascript
# Scenario: Update Enrol user
# Given I am on "Course 001" course homepage
# And I navigate to course participants
# When I click on "Edit enrolment" "icon" in the "Teacher 001" "table_row"
# Then the "Enrolment duration" "select" should be enabled
# # Fill duration
# And "input[name='timeend[enabled]'][checked=checked]" "css_element" should not exist
# And the "Enrolment duration" "select" should be enabled
# And I set the field "duration" to "2"
# # Fill end time
# And I set the field "timeend[enabled]" to "1"
# And I set the field "timeend[day]" to "28"
# And the "Enrolment duration" "select" should be disabled
# And I press "Save changes"
# And I click on "Edit enrolment" "icon" in the "Teacher 001" "table_row"
# And the field "timeend[day]" matches value "28"
@@ -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"
+298
View File
@@ -0,0 +1,298 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace enrol_manual;
use enrol_manual_external;
use externallib_advanced_testcase;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/enrol/manual/externallib.php');
/**
* Enrol manual external PHPunit tests
*
* @package enrol_manual
* @category phpunit
* @copyright 2012 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.4
*/
class externallib_test extends externallib_advanced_testcase {
/**
* Test get_enrolled_users
*/
public function test_enrol_users(): void {
global $DB;
$this->resetAfterTest(true);
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
$course1 = self::getDataGenerator()->create_course();
$course2 = self::getDataGenerator()->create_course();
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
$context1 = \context_course::instance($course1->id);
$context2 = \context_course::instance($course2->id);
$instance1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
$instance2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST);
// Set the required capabilities by the external function.
$roleid = $this->assignUserCapability('enrol/manual:enrol', $context1->id);
$this->assignUserCapability('moodle/course:view', $context1->id, $roleid);
$this->assignUserCapability('moodle/role:assign', $context1->id, $roleid);
$this->assignUserCapability('enrol/manual:enrol', $context2->id, $roleid);
$this->assignUserCapability('moodle/course:view', $context2->id, $roleid);
$this->assignUserCapability('moodle/role:assign', $context2->id, $roleid);
core_role_set_assign_allowed($roleid, 3);
// Call the external function.
enrol_manual_external::enrol_users(array(
array('roleid' => 3, 'userid' => $user1->id, 'courseid' => $course1->id),
array('roleid' => 3, 'userid' => $user2->id, 'courseid' => $course1->id),
));
$this->assertEquals(2, $DB->count_records('user_enrolments', array('enrolid' => $instance1->id)));
$this->assertEquals(0, $DB->count_records('user_enrolments', array('enrolid' => $instance2->id)));
$this->assertTrue(is_enrolled($context1, $user1));
$this->assertTrue(is_enrolled($context1, $user2));
// Call without required capability.
$DB->delete_records('user_enrolments');
$this->unassignUserCapability('enrol/manual:enrol', $context1->id, $roleid);
try {
enrol_manual_external::enrol_users(array(
array('roleid' => 3, 'userid' => $user1->id, 'courseid' => $course1->id),
));
$this->fail('Exception expected if not having capability to enrol');
} catch (\moodle_exception $e) {
$this->assertInstanceOf('required_capability_exception', $e);
$this->assertSame('nopermissions', $e->errorcode);
}
$this->assignUserCapability('enrol/manual:enrol', $context1->id, $roleid);
$this->assertEquals(0, $DB->count_records('user_enrolments'));
// Call with forbidden role.
try {
enrol_manual_external::enrol_users(array(
array('roleid' => 1, 'userid' => $user1->id, 'courseid' => $course1->id),
));
$this->fail('Exception expected if not allowed to assign role.');
} catch (\moodle_exception $e) {
$this->assertSame('wsusercannotassign', $e->errorcode);
}
$this->assertEquals(0, $DB->count_records('user_enrolments'));
// Call for course without manual instance.
$DB->delete_records('user_enrolments');
$DB->delete_records('enrol', array('courseid' => $course2->id));
try {
enrol_manual_external::enrol_users(array(
array('roleid' => 3, 'userid' => $user1->id, 'courseid' => $course1->id),
array('roleid' => 3, 'userid' => $user1->id, 'courseid' => $course2->id),
));
$this->fail('Exception expected if course does not have manual instance');
} catch (\moodle_exception $e) {
$this->assertSame('wsnoinstance', $e->errorcode);
$this->assertSame(
"Manual enrolment plugin instance doesn't exist or is disabled for the course (id = {$course2->id})",
$e->getMessage()
);
}
}
/**
* Test for unerolling a single user.
* @throws coding_exception
* @throws invalid_parameter_exception
* @throws moodle_exception
*/
public function test_unenrol_user_single(): void {
global $CFG, $DB;
require_once($CFG->libdir . '/enrollib.php');
$this->resetAfterTest(true);
// The user who perform the action.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user); // Log this user in.
$enrol = enrol_get_plugin('manual');
// Create a course.
$course = self::getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
// Set the capability for the user.
$roleid = $this->assignUserCapability('enrol/manual:enrol', $coursecontext);
$this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid);
$this->assignUserCapability('moodle/course:view', $coursecontext, $roleid);
$this->assignUserCapability('moodle/role:assign', $coursecontext, $roleid);
// Create a student and enrol them into the course.
$student = $this->getDataGenerator()->create_user();
$enrol->enrol_user($enrolinstance, $student->id);
$this->assertTrue(is_enrolled($coursecontext, $student));
// Call the web service to unenrol.
enrol_manual_external::unenrol_users(array(
array('userid' => $student->id, 'courseid' => $course->id),
));
$this->assertFalse(is_enrolled($coursecontext, $student));
}
/**
* Test for unenrolling multiple users.
* @throws coding_exception
* @throws invalid_parameter_exception
* @throws moodle_exception
*/
public function test_unenrol_user_multiple(): void {
global $CFG, $DB;
require_once($CFG->libdir . '/enrollib.php');
$this->resetAfterTest(true);
// The user who perform the action.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user); // Log this user in.
// Create a course.
$course = self::getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
// Set the capability for the user.
$roleid = $this->assignUserCapability('enrol/manual:enrol', $coursecontext);
$this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid);
$this->assignUserCapability('moodle/course:view', $coursecontext, $roleid);
$this->assignUserCapability('moodle/role:assign', $coursecontext, $roleid);
$enrol = enrol_get_plugin('manual');
// Create a student and enrol them into the course.
$student1 = $this->getDataGenerator()->create_user();
$enrol->enrol_user($enrolinstance, $student1->id);
$this->assertTrue(is_enrolled($coursecontext, $student1));
$student2 = $this->getDataGenerator()->create_user();
$enrol->enrol_user($enrolinstance, $student2->id);
$this->assertTrue(is_enrolled($coursecontext, $student2));
// Call the web service to unenrol.
enrol_manual_external::unenrol_users(array(
array('userid' => $student1->id, 'courseid' => $course->id),
array('userid' => $student2->id, 'courseid' => $course->id),
));
$this->assertFalse(is_enrolled($coursecontext, $student1));
$this->assertFalse(is_enrolled($coursecontext, $student2));
}
/**
* Test for unenrol capability.
* @throws coding_exception
* @throws invalid_parameter_exception
* @throws moodle_exception
*/
public function test_unenrol_user_error_no_capability(): void {
global $CFG, $DB;
require_once($CFG->libdir . '/enrollib.php');
$this->resetAfterTest(true);
// The user who perform the action.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user); // Log this user in.
// Create a course.
$course = self::getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
$enrol = enrol_get_plugin('manual');
// Create a student and enrol them into the course.
$student = $this->getDataGenerator()->create_user();
$enrol->enrol_user($enrolinstance, $student->id);
$this->assertTrue(is_enrolled($coursecontext, $student));
// Call the web service to unenrol.
try {
enrol_manual_external::unenrol_users(array(
array('userid' => $student->id, 'courseid' => $course->id),
));
$this->fail('Exception expected: User cannot log in to the course');
} catch (\Exception $ex) {
$this->assertTrue($ex instanceof \require_login_exception);
}
// Set the capability for the course, then try again.
$roleid = $this->assignUserCapability('moodle/course:view', $coursecontext);
try {
enrol_manual_external::unenrol_users(array(
array('userid' => $student->id, 'courseid' => $course->id),
));
$this->fail('Exception expected: User cannot log in to the course');
} catch (\Exception $ex) {
$this->assertTrue($ex instanceof \required_capability_exception);
}
// Assign unenrol capability.
$this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid);
enrol_manual_external::unenrol_users(array(
array('userid' => $student->id, 'courseid' => $course->id),
));
$this->assertFalse(is_enrolled($coursecontext, $student));
}
/**
* Test for unenrol if user does not exist.
* @throws coding_exception
*/
public function test_unenrol_user_error_not_exist(): void {
global $CFG, $DB;
require_once($CFG->libdir . '/enrollib.php');
$this->resetAfterTest(true);
// The user who perform the action.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user); // Log this user in.
$enrol = enrol_get_plugin('manual');
// Create a course.
$course = self::getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
// Set the capability for the user.
$roleid = $this->assignUserCapability('enrol/manual:enrol', $coursecontext);
$this->assignUserCapability('enrol/manual:unenrol', $coursecontext, $roleid);
$this->assignUserCapability('moodle/course:view', $coursecontext, $roleid);
$this->assignUserCapability('moodle/role:assign', $coursecontext, $roleid);
// Create a student and enrol them into the course.
$student = $this->getDataGenerator()->create_user();
$enrol->enrol_user($enrolinstance, $student->id);
$this->assertTrue(is_enrolled($coursecontext, $student));
try {
enrol_manual_external::unenrol_users(array(
array('userid' => $student->id + 1, 'courseid' => $course->id),
));
$this->fail('Exception expected: invalid student id');
} catch (\Exception $ex) {
$this->assertTrue($ex instanceof \invalid_parameter_exception);
}
// Call for course without manual instance.
$DB->delete_records('user_enrolments');
$DB->delete_records('enrol', ['courseid' => $course->id]);
try {
enrol_manual_external::unenrol_users(array(
array('userid' => $student->id + 1, 'courseid' => $course->id),
));
$this->fail('Exception expected if course does not have manual instance');
} catch (\moodle_exception $e) {
$this->assertSame('wsnoinstance', $e->errorcode);
$this->assertSame(
"Manual enrolment plugin instance doesn't exist or is disabled for the course (id = {$course->id})",
$e->getMessage()
);
}
}
}
+945
View File
@@ -0,0 +1,945 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual enrolment tests.
*
* @package enrol_manual
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_manual;
use course_enrolment_manager;
use stdClass;
defined('MOODLE_INTERNAL') || die();
/**
* Manual enrolment tests.
*
* @package enrol_manual
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class lib_test extends \advanced_testcase {
/**
* Test enrol migration function used when uninstalling enrol plugins.
*/
public function test_migrate_plugin_enrolments(): void {
global $DB, $CFG;
require_once($CFG->dirroot.'/enrol/manual/locallib.php');
$this->resetAfterTest();
/** @var $manplugin enrol_manual_plugin */
$manplugin = enrol_get_plugin('manual');
// Setup a few courses and users.
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->assertNotEmpty($studentrole);
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->assertNotEmpty($teacherrole);
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$course4 = $this->getDataGenerator()->create_course();
$course5 = $this->getDataGenerator()->create_course();
$context1 = \context_course::instance($course1->id);
$context2 = \context_course::instance($course2->id);
$context3 = \context_course::instance($course3->id);
$context4 = \context_course::instance($course4->id);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
// We expect manual, self and guest instances to be created by default.
$this->assertEquals(5, $DB->count_records('enrol', array('enrol'=>'manual')));
$this->assertEquals(5, $DB->count_records('enrol', array('enrol'=>'self')));
$this->assertEquals(5, $DB->count_records('enrol', array('enrol'=>'guest')));
$this->assertEquals(15, $DB->count_records('enrol', array()));
$this->assertEquals(0, $DB->count_records('user_enrolments', array()));
// Enrol some users to manual instances.
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$maninstance1->id));
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$DB->delete_records('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'));
$DB->delete_records('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'));
$DB->delete_records('enrol', array('courseid'=>$course5->id, 'enrol'=>'manual'));
$manplugin->enrol_user($maninstance1, $user1->id, $studentrole->id);
$manplugin->enrol_user($maninstance1, $user2->id, $studentrole->id);
$manplugin->enrol_user($maninstance1, $user3->id, $teacherrole->id);
$manplugin->enrol_user($maninstance2, $user3->id, $teacherrole->id);
$this->assertEquals(4, $DB->count_records('user_enrolments', array()));
// Set up some bogus enrol plugin instances and enrolments.
$xxxinstance1 = $DB->insert_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'xxx', 'status'=>ENROL_INSTANCE_ENABLED));
$xxxinstance1 = $DB->get_record('enrol', array('id'=>$xxxinstance1));
$xxxinstance3 = $DB->insert_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'xxx', 'status'=>ENROL_INSTANCE_DISABLED));
$xxxinstance3 = $DB->get_record('enrol', array('id'=>$xxxinstance3));
$xxxinstance4 = $DB->insert_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'xxx', 'status'=>ENROL_INSTANCE_ENABLED));
$xxxinstance4 = $DB->get_record('enrol', array('id'=>$xxxinstance4));
$xxxinstance4b = $DB->insert_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'xxx', 'status'=>ENROL_INSTANCE_DISABLED));
$xxxinstance4b = $DB->get_record('enrol', array('id'=>$xxxinstance4b));
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance1->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_SUSPENDED));
role_assign($studentrole->id, $user1->id, $context1->id, 'enrol_xxx', $xxxinstance1->id);
role_assign($teacherrole->id, $user1->id, $context1->id, 'enrol_xxx', $xxxinstance1->id);
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance1->id, 'userid'=>$user4->id, 'status'=>ENROL_USER_ACTIVE));
role_assign($studentrole->id, $user4->id, $context1->id, 'enrol_xxx', $xxxinstance1->id);
$this->assertEquals(2, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance1->id)));
$this->assertEquals(6, $DB->count_records('role_assignments', array('contextid'=>$context1->id)));
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance3->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_ACTIVE));
role_assign($studentrole->id, $user1->id, $context3->id, 'enrol_xxx', $xxxinstance3->id);
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance3->id, 'userid'=>$user2->id, 'status'=>ENROL_USER_SUSPENDED));
$this->assertEquals(2, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance3->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('contextid'=>$context3->id)));
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance4->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_ACTIVE));
role_assign($studentrole->id, $user1->id, $context4->id, 'enrol_xxx', $xxxinstance4->id);
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance4->id, 'userid'=>$user2->id, 'status'=>ENROL_USER_ACTIVE));
role_assign($studentrole->id, $user2->id, $context4->id, 'enrol_xxx', $xxxinstance4->id);
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance4b->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_SUSPENDED));
role_assign($teacherrole->id, $user1->id, $context4->id, 'enrol_xxx', $xxxinstance4b->id);
$DB->insert_record('user_enrolments', array('enrolid'=>$xxxinstance4b->id, 'userid'=>$user4->id, 'status'=>ENROL_USER_ACTIVE));
role_assign($teacherrole->id, $user4->id, $context4->id, 'enrol_xxx', $xxxinstance4b->id);
$this->assertEquals(2, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance4->id)));
$this->assertEquals(2, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance4b->id)));
$this->assertEquals(4, $DB->count_records('role_assignments', array('contextid'=>$context4->id)));
// Finally do the migration.
enrol_manual_migrate_plugin_enrolments('xxx');
// Verify results.
$this->assertEquals(1, $DB->count_records('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual')));
$this->assertEquals(1, $DB->count_records('enrol', array('courseid'=>$course1->id, 'enrol'=>'xxx')));
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals(ENROL_INSTANCE_DISABLED, $maninstance1->status);
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user2->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user3->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user4->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertEquals(4, $DB->count_records('user_enrolments', array('enrolid'=>$maninstance1->id)));
$this->assertEquals(0, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance1->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'contextid'=>$context1->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user1->id, 'roleid'=>$teacherrole->id, 'contextid'=>$context1->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user2->id, 'roleid'=>$studentrole->id, 'contextid'=>$context1->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user3->id, 'roleid'=>$teacherrole->id, 'contextid'=>$context1->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user4->id, 'roleid'=>$studentrole->id, 'contextid'=>$context1->id)));
$this->assertEquals(5, $DB->count_records('role_assignments', array('contextid'=>$context1->id)));
$this->assertEquals(1, $DB->count_records('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual')));
$this->assertEquals(0, $DB->count_records('enrol', array('courseid'=>$course2->id, 'enrol'=>'xxx')));
$maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals(ENROL_INSTANCE_ENABLED, $maninstance2->status);
$this->assertEquals(1, $DB->count_records('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual')));
$this->assertEquals(1, $DB->count_records('enrol', array('courseid'=>$course3->id, 'enrol'=>'xxx')));
$maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals(ENROL_INSTANCE_DISABLED, $maninstance3->status);
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance3->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance3->id, 'userid'=>$user2->id, 'status'=>ENROL_USER_SUSPENDED)));
$this->assertEquals(2, $DB->count_records('user_enrolments', array('enrolid'=>$maninstance3->id)));
$this->assertEquals(0, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance3->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'contextid'=>$context3->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('contextid'=>$context3->id)));
$this->assertEquals(1, $DB->count_records('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual')));
$this->assertEquals(2, $DB->count_records('enrol', array('courseid'=>$course4->id, 'enrol'=>'xxx')));
$maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals(ENROL_INSTANCE_ENABLED, $maninstance4->status);
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance4->id, 'userid'=>$user1->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance4->id, 'userid'=>$user2->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance4->id, 'userid'=>$user4->id, 'status'=>ENROL_USER_SUSPENDED)));
$this->assertEquals(3, $DB->count_records('user_enrolments', array('enrolid'=>$maninstance4->id)));
$this->assertEquals(0, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance4->id)));
$this->assertEquals(0, $DB->count_records('user_enrolments', array('enrolid'=>$xxxinstance4b->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'contextid'=>$context4->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user1->id, 'roleid'=>$teacherrole->id, 'contextid'=>$context4->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user2->id, 'roleid'=>$studentrole->id, 'contextid'=>$context4->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('itemid'=>0, 'component'=>'', 'userid'=>$user4->id, 'roleid'=>$teacherrole->id, 'contextid'=>$context4->id)));
$this->assertEquals(4, $DB->count_records('role_assignments', array('contextid'=>$context4->id)));
$this->assertEquals(0, $DB->count_records('enrol', array('courseid'=>$course5->id, 'enrol'=>'manual')));
$this->assertEquals(0, $DB->count_records('enrol', array('courseid'=>$course5->id, 'enrol'=>'xxx')));
// Make sure wrong params do not produce errors or notices.
enrol_manual_migrate_plugin_enrolments('manual');
enrol_manual_migrate_plugin_enrolments('yyyy');
}
public function test_expired(): void {
global $DB;
$this->resetAfterTest();
/** @var $manualplugin enrol_manual_plugin */
$manualplugin = enrol_get_plugin('manual');
$trace = new \null_progress_trace();
$now = time();
// Prepare some data.
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->assertNotEmpty($studentrole);
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->assertNotEmpty($teacherrole);
$managerrole = $DB->get_record('role', array('shortname'=>'manager'));
$this->assertNotEmpty($managerrole);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$context1 = \context_course::instance($course1->id);
$context2 = \context_course::instance($course2->id);
$context3 = \context_course::instance($course3->id);
$this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'manual')));
$instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals($studentrole->id, $instance1->roleid);
$instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals($studentrole->id, $instance2->roleid);
$instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals($studentrole->id, $instance3->roleid);
$this->assertEquals(0, $DB->count_records('user_enrolments'));
$this->assertEquals(0, $DB->count_records('role_assignments'));
$manualplugin->enrol_user($instance1, $user1->id, $studentrole->id);
$manualplugin->enrol_user($instance1, $user2->id, $studentrole->id);
$manualplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now-60);
$manualplugin->enrol_user($instance3, $user1->id, $studentrole->id, 0, 0);
$manualplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now+60*60);
$manualplugin->enrol_user($instance3, $user3->id, $teacherrole->id, 0, $now-60*60);
role_assign($managerrole->id, $user4->id, $context1->id);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(7, $DB->count_records('role_assignments'));
$this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
// Execute tests.
$this->assertEquals(ENROL_EXT_REMOVED_KEEP, $manualplugin->get_config('expiredaction'));
$manualplugin->sync($trace, null);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(7, $DB->count_records('role_assignments'));
$manualplugin->set_config('expiredaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
$manualplugin->sync($trace, $course2->id);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(7, $DB->count_records('role_assignments'));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user3->id, 'roleid'=>$studentrole->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user3->id, 'roleid'=>$teacherrole->id)));
$manualplugin->sync($trace, null);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(5, $DB->count_records('role_assignments'));
$this->assertEquals(4, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(0, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user3->id, 'roleid'=>$studentrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user3->id, 'roleid'=>$teacherrole->id)));
$manualplugin->set_config('expiredaction', ENROL_EXT_REMOVED_UNENROL);
role_assign($studentrole->id, $user3->id, $context1->id);
role_assign($teacherrole->id, $user3->id, $context3->id);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(7, $DB->count_records('role_assignments'));
$this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
$manualplugin->sync($trace, null);
$this->assertEquals(4, $DB->count_records('user_enrolments'));
$this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user3->id)));
$this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user3->id)));
$this->assertEquals(5, $DB->count_records('role_assignments'));
$this->assertEquals(4, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(0, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
$manualplugin->set_config('expiredaction', ENROL_EXT_REMOVED_SUSPEND);
$manualplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now-60);
$manualplugin->enrol_user($instance3, $user3->id, $teacherrole->id, 0, $now-60*60);
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$maninstance2 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(7, $DB->count_records('role_assignments'));
$this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user3->id, 'status'=>ENROL_USER_ACTIVE)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance2->id, 'userid'=>$user3->id, 'status'=>ENROL_USER_ACTIVE)));
$manualplugin->sync($trace, null);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user3->id)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user3->id)));
$this->assertEquals(7, $DB->count_records('role_assignments'));
$this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance1->id, 'userid'=>$user3->id, 'status'=>ENROL_USER_SUSPENDED)));
$this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$maninstance2->id, 'userid'=>$user3->id, 'status'=>ENROL_USER_SUSPENDED)));
}
public function test_send_expiry_notifications(): void {
global $DB, $CFG;
$this->resetAfterTest();
$this->preventResetByRollback(); // Messaging does not like transactions...
$trace = new \null_progress_trace();
/** @var $manualplugin enrol_manual_plugin */
$manualplugin = enrol_get_plugin('manual');
$now = time();
$admin = get_admin();
// Note: hopefully nobody executes the unit tests the last second before midnight...
$manualplugin->set_config('expirynotifylast', $now - 60*60*24);
$manualplugin->set_config('expirynotifyhour', 0);
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->assertNotEmpty($studentrole);
$editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
$this->assertNotEmpty($editingteacherrole);
$managerrole = $DB->get_record('role', array('shortname'=>'manager'));
$this->assertNotEmpty($managerrole);
$user1 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser1'));
$user2 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser2'));
$user3 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser3'));
$user4 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser4'));
$user5 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser5'));
$user6 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
$user7 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
$user8 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
$course1 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse1'));
$course2 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse2'));
$course3 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse3'));
$course4 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse4'));
$this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'manual')));
$instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$instance1->expirythreshold = 60*60*24*4;
$instance1->expirynotify = 1;
$instance1->notifyall = 1;
$DB->update_record('enrol', $instance1);
$instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$instance2->expirythreshold = 60*60*24*1;
$instance2->expirynotify = 1;
$instance2->notifyall = 1;
$DB->update_record('enrol', $instance2);
$instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$instance3->expirythreshold = 60*60*24*1;
$instance3->expirynotify = 1;
$instance3->notifyall = 0;
$DB->update_record('enrol', $instance3);
$instance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$instance4->expirythreshold = 60*60*24*1;
$instance4->expirynotify = 0;
$instance4->notifyall = 0;
$DB->update_record('enrol', $instance4);
$manualplugin->enrol_user($instance1, $user1->id, $editingteacherrole->id, 0, $now + 60*60*24*1, ENROL_USER_SUSPENDED); // Suspended users are not notified.
$manualplugin->enrol_user($instance1, $user2->id, $studentrole->id, 0, $now + 60*60*24*5); // Above threshold are not notified.
$manualplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now + 60*60*24*3 + 60*60); // Less than one day after threshold - should be notified.
$manualplugin->enrol_user($instance1, $user4->id, $studentrole->id, 0, $now + 60*60*24*4 - 60*3); // Less than one day after threshold - should be notified.
$manualplugin->enrol_user($instance1, $user5->id, $studentrole->id, 0, $now + 60*60); // Should have been already notified.
$manualplugin->enrol_user($instance1, $user6->id, $studentrole->id, 0, $now - 60); // Already expired.
$manualplugin->enrol_user($instance1, $user7->id, $editingteacherrole->id);
$manualplugin->enrol_user($instance1, $user8->id, $managerrole->id); // Highest role --> enroller.
$manualplugin->enrol_user($instance2, $user1->id, $studentrole->id);
$manualplugin->enrol_user($instance2, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60*3); // Above threshold are not notified.
$manualplugin->enrol_user($instance2, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60); // Less than one day after threshold - should be notified.
$manualplugin->enrol_user($instance3, $user1->id, $editingteacherrole->id);
$manualplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60); // Above threshold are not notified.
$manualplugin->enrol_user($instance3, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60); // Less than one day after threshold - should be notified.
$manualplugin->enrol_user($instance4, $user4->id, $editingteacherrole->id);
$manualplugin->enrol_user($instance4, $user5->id, $studentrole->id, 0, $now + 60*60*24*1 + 60);
$manualplugin->enrol_user($instance4, $user6->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);
// The notification is sent out in fixed order first individual users,
// then summary per course by enrolid, user lastname, etc.
$this->assertGreaterThan($instance1->id, $instance2->id);
$this->assertGreaterThan($instance2->id, $instance3->id);
$sink = $this->redirectMessages();
$manualplugin->send_expiry_notifications($trace);
$messages = $sink->get_messages();
$this->assertEquals(2+1 + 1+1 + 1 + 0, count($messages));
// First individual notifications from course1.
$this->assertEquals($user3->id, $messages[0]->useridto);
$this->assertEquals($user8->id, $messages[0]->useridfrom);
$this->assertStringContainsString('xcourse1', $messages[0]->fullmessagehtml);
$this->assertEquals($user4->id, $messages[1]->useridto);
$this->assertEquals($user8->id, $messages[1]->useridfrom);
$this->assertStringContainsString('xcourse1', $messages[1]->fullmessagehtml);
// Then summary for course1.
$this->assertEquals($user8->id, $messages[2]->useridto);
$this->assertEquals($admin->id, $messages[2]->useridfrom);
$this->assertStringContainsString('xcourse1', $messages[2]->fullmessagehtml);
$this->assertStringNotContainsString('xuser1', $messages[2]->fullmessagehtml);
$this->assertStringNotContainsString('xuser2', $messages[2]->fullmessagehtml);
$this->assertStringContainsString('xuser3', $messages[2]->fullmessagehtml);
$this->assertStringContainsString('xuser4', $messages[2]->fullmessagehtml);
$this->assertStringContainsString('xuser5', $messages[2]->fullmessagehtml);
$this->assertStringNotContainsString('xuser6', $messages[2]->fullmessagehtml);
// First individual notifications from course2.
$this->assertEquals($user3->id, $messages[3]->useridto);
$this->assertEquals($admin->id, $messages[3]->useridfrom);
$this->assertStringContainsString('xcourse2', $messages[3]->fullmessagehtml);
// Then summary for course2.
$this->assertEquals($admin->id, $messages[4]->useridto);
$this->assertEquals($admin->id, $messages[4]->useridfrom);
$this->assertStringContainsString('xcourse2', $messages[4]->fullmessagehtml);
$this->assertStringNotContainsString('xuser1', $messages[4]->fullmessagehtml);
$this->assertStringNotContainsString('xuser2', $messages[4]->fullmessagehtml);
$this->assertStringContainsString('xuser3', $messages[4]->fullmessagehtml);
$this->assertStringNotContainsString('xuser4', $messages[4]->fullmessagehtml);
$this->assertStringNotContainsString('xuser5', $messages[4]->fullmessagehtml);
$this->assertStringNotContainsString('xuser6', $messages[4]->fullmessagehtml);
// Only summary in course3.
$this->assertEquals($user1->id, $messages[5]->useridto);
$this->assertEquals($admin->id, $messages[5]->useridfrom);
$this->assertStringContainsString('xcourse3', $messages[5]->fullmessagehtml);
$this->assertStringNotContainsString('xuser1', $messages[5]->fullmessagehtml);
$this->assertStringNotContainsString('xuser2', $messages[5]->fullmessagehtml);
$this->assertStringContainsString('xuser3', $messages[5]->fullmessagehtml);
$this->assertStringNotContainsString('xuser4', $messages[5]->fullmessagehtml);
$this->assertStringNotContainsString('xuser5', $messages[5]->fullmessagehtml);
$this->assertStringNotContainsString('xuser6', $messages[5]->fullmessagehtml);
// Make sure that notifications are not repeated.
$sink->clear();
$manualplugin->send_expiry_notifications($trace);
$this->assertEquals(0, $sink->count());
// use invalid notification hour to verify that before the hour the notifications are not sent.
$manualplugin->set_config('expirynotifylast', time() - 60*60*24);
$manualplugin->set_config('expirynotifyhour', '24');
$manualplugin->send_expiry_notifications($trace);
$this->assertEquals(0, $sink->count());
$manualplugin->set_config('expirynotifyhour', '0');
$manualplugin->send_expiry_notifications($trace);
$this->assertEquals(6, $sink->count());
}
/**
* Test for getting user enrolment actions.
*/
public function test_get_user_enrolment_actions(): void {
global $CFG, $PAGE;
$this->resetAfterTest();
// Set page URL to prevent debugging messages.
$PAGE->set_url('/enrol/editinstance.php');
$pluginname = 'manual';
// Only enable the manual enrol plugin.
$CFG->enrol_plugins_enabled = $pluginname;
$generator = $this->getDataGenerator();
// Get the enrol plugin.
$plugin = enrol_get_plugin($pluginname);
// Create a course.
$course = $generator->create_course();
// Enable this enrol plugin for the course.
$plugin->add_instance($course);
// Create a teacher.
$teacher = $generator->create_user();
// Enrol the teacher to the course.
$generator->enrol_user($teacher->id, $course->id, 'editingteacher', $pluginname);
// Create a student.
$student = $generator->create_user();
// Enrol the student to the course.
$generator->enrol_user($student->id, $course->id, 'student', $pluginname);
// Login as the teacher.
$this->setUser($teacher);
require_once($CFG->dirroot . '/enrol/locallib.php');
$manager = new course_enrolment_manager($PAGE, $course);
$userenrolments = $manager->get_user_enrolments($student->id);
$this->assertCount(1, $userenrolments);
$ue = reset($userenrolments);
$actions = $plugin->get_user_enrolment_actions($manager, $ue);
// Manual enrol has 2 enrol actions -- edit and unenrol.
$this->assertCount(2, $actions);
}
/**
* Test how the default enrolment instance inherits its settings from the global plugin settings.
*
* @dataProvider default_enrolment_instance_data_provider
* @param stdClass $expectation
* @param stdClass $globalsettings
* @covers \enrol_manual::add_default_instance
*/
public function test_default_enrolment_instance_acquires_correct_settings(stdClass $expectation, stdClass $globalsettings): void {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
// Given the plugin is globally configured with the following settings.
$plugin = enrol_get_plugin('manual');
$plugin->set_config('status', $globalsettings->status);
$plugin->set_config('roleid', $globalsettings->roleid);
$plugin->set_config('enrolperiod', $globalsettings->enrolperiod);
$plugin->set_config('expirynotify', $globalsettings->expirynotify);
$plugin->set_config('expirythreshold', $globalsettings->expirythreshold);
// When creating a course.
$course = $generator->create_course();
// Then the default manual enrolment instance being created is properly configured.
$enrolinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual']);
$this->assertEquals($expectation->status, $enrolinstance->status);
$this->assertEquals($expectation->roleid, $enrolinstance->roleid);
$this->assertEquals($expectation->enrolperiod, $enrolinstance->enrolperiod);
$this->assertEquals($expectation->expirynotify, $enrolinstance->expirynotify);
$this->assertEquals($expectation->notifyall, $enrolinstance->notifyall);
$this->assertEquals($expectation->expirythreshold, $enrolinstance->expirythreshold);
}
/**
* Data provider for test_default_enrolment_instance_acquires_correct_settings().
*
* @return array
*/
public function default_enrolment_instance_data_provider(): array {
$studentroles = get_archetype_roles('student');
$studentrole = array_shift($studentroles);
$teacherroles = get_archetype_roles('teacher');
$teacherrole = array_shift($teacherroles);
return [
'enabled, student role, no duration set, notify no one on expiry, 12 hours notification threshold' => [
'expectation' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 0,
'expirynotify' => 0,
'notifyall' => 0,
'expirythreshold' => 12 * HOURSECS,
],
'global settings' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 0,
'expirynotify' => 0,
'expirythreshold' => 12 * HOURSECS,
],
],
'enabled, student role, 72 hours duration, notify enroller only on expiry, 1 day notification threshold' => [
'expectation' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 72 * HOURSECS,
'expirynotify' => 1,
'notifyall' => 0,
'expirythreshold' => DAYSECS,
],
'global settings' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 72 * HOURSECS,
'expirynotify' => 1,
'expirythreshold' => DAYSECS,
],
],
'disabled, teacher role, no duration set, notify enroller and enrolled on expiry, 0 notification threshold' => [
'expectation' => (object) [
'status' => ENROL_INSTANCE_DISABLED,
'roleid' => $teacherrole->id,
'enrolperiod' => 0,
'expirynotify' => 2,
'notifyall' => 1,
'expirythreshold' => 0
],
'global settings' => (object) [
'status' => ENROL_INSTANCE_DISABLED,
'roleid' => $teacherrole->id,
'enrolperiod' => 0,
'expirynotify' => 2,
'expirythreshold' => 0,
],
],
];
}
/**
* Tests an enrolment instance is updated properly.
*
* @covers \enrol_manual::update_instance
* @dataProvider update_enrolment_instance_data_provider
*
* @param stdClass $expectation
* @param stdClass $updatedata
*/
public function test_enrolment_instance_is_updated(stdClass $expectation, stdClass $updatedata): void {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$studentroles = get_archetype_roles('student');
$studentrole = array_shift($studentroles);
// Given the plugin is globally configured with the following settings.
$plugin = enrol_get_plugin('manual');
$plugin->set_config('status', ENROL_INSTANCE_ENABLED);
$plugin->set_config('roleid', $studentrole->id);
$plugin->set_config('enrolperiod', 30 * DAYSECS);
$plugin->set_config('expirynotify', 1);
$plugin->set_config('expirythreshold', 2 * DAYSECS);
// And a course is created with the default enrolment instance.
$course = $generator->create_course();
// When the enrolment instance is being updated.
$enrolinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual']);
$successfullyupdated = $plugin->update_instance($enrolinstance, $updatedata);
// Then the update is successful.
$this->assertTrue($successfullyupdated);
// And the updated enrolment instance contains the expected values.
$enrolinstance = $DB->get_record('enrol', ['id' => $enrolinstance->id]);
$this->assertEquals($expectation->status, $enrolinstance->status);
$this->assertEquals($expectation->roleid, $enrolinstance->roleid);
$this->assertEquals($expectation->enrolperiod, $enrolinstance->enrolperiod);
$this->assertEquals($expectation->expirynotify, $enrolinstance->expirynotify);
$this->assertEquals($expectation->notifyall, $enrolinstance->notifyall);
$this->assertEquals($expectation->expirythreshold, $enrolinstance->expirythreshold);
}
/**
* Data provider for test_enrolment_instance_is_updated().
*
* @return array
*/
public function update_enrolment_instance_data_provider(): array {
$studentroles = get_archetype_roles('student');
$studentrole = array_shift($studentroles);
$teacherroles = get_archetype_roles('teacher');
$teacherrole = array_shift($teacherroles);
return [
'disabled, all the others are default' => [
'expectation' => (object) [
'status' => ENROL_INSTANCE_DISABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 30 * DAYSECS,
'expirynotify' => 1,
'notifyall' => 0,
'expirythreshold' => 2 * DAYSECS,
],
'update data' => (object) [
'status' => ENROL_INSTANCE_DISABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 30 * DAYSECS,
'expirynotify' => 1,
'expirythreshold' => 2 * DAYSECS,
],
],
'enabled, teacher role, no duration set, notify no one on expiry, 0 notification threshold' => [
'expectation' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $teacherrole->id,
'enrolperiod' => 0,
'expirynotify' => 0,
'notifyall' => 0,
'expirythreshold' => 0,
],
'update data' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $teacherrole->id,
'enrolperiod' => 0,
'expirynotify' => 0,
'expirythreshold' => 0,
],
],
'notify enroller and enrolled on expiry, all the others are default' => [
'expectation' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 30 * DAYSECS,
'expirynotify' => 2,
'notifyall' => 1,
'expirythreshold' => 2 * DAYSECS,
],
'update data' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 30 * DAYSECS,
'expirynotify' => 2,
'expirythreshold' => 2 * DAYSECS,
],
],
];
}
/**
* Test the behaviour of find_instance().
*
* @covers ::find_instance
*/
public function test_find_instance(): void {
global $DB;
$this->resetAfterTest();
$cat = $this->getDataGenerator()->create_category();
// When we create a course, a manual enrolment instance is also created.
$course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']);
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$manualplugin = enrol_get_plugin('manual');
$expected = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual']);
// Let's try to add second instance - only 1 manual instance is possible.
$instanceid2 = $manualplugin->add_instance($course, ['roleid' => $teacherrole->id]);
$this->assertNull($instanceid2);
$enrolmentdata = [];
$actual = $manualplugin->find_instance($enrolmentdata, $course->id);
$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 & 2',
'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}, ' .
'your course: {$a->coursename}',
);
$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 . ', your course: ' . $course->fullname,
$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);
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual enrolment plugin - support for user self unenrolment.
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require('../../config.php');
$enrolid = required_param('enrolid', PARAM_INT);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$instance = $DB->get_record('enrol', array('id'=>$enrolid, 'enrol'=>'manual'), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
$context = context_course::instance($course->id, MUST_EXIST);
require_login();
if (!is_enrolled($context)) {
redirect(new moodle_url('/'));
}
require_login($course);
$plugin = enrol_get_plugin('manual');
// Security defined inside following function.
if (!$plugin->get_unenrolself_link($instance)) {
redirect(new moodle_url('/course/view.php', array('id'=>$course->id)));
}
$PAGE->set_url('/enrol/manual/unenrolself.php', array('enrolid'=>$instance->id));
$PAGE->set_title($plugin->get_instance_name($instance));
if ($confirm and confirm_sesskey()) {
$plugin->unenrol_user($instance, $USER->id);
redirect(new moodle_url('/index.php'));
}
echo $OUTPUT->header();
$yesurl = new moodle_url($PAGE->url, array('confirm'=>1, 'sesskey'=>sesskey()));
$nourl = new moodle_url('/course/view.php', array('id'=>$course->id));
$message = get_string('unenrolselfconfirm', 'enrol_manual', format_string($course->fullname));
echo $OUTPUT->confirm($message, $yesurl, $nourl);
echo $OUTPUT->footer();
+29
View File
@@ -0,0 +1,29 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Manual enrolment plugin version specification.
*
* @package enrol_manual
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'enrol_manual'; // Full name of the plugin (used for diagnostics)