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
+57
View File
@@ -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/>.
/**
* Special flatfile settings.
*
* @package enrol_flatfile
* @copyright 2013 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->libdir/adminlib.php");
/**
* Setting class that stores only non-empty values.
*/
class enrol_flatfile_role_setting extends admin_setting_configtext {
public function __construct($role) {
parent::__construct('enrol_flatfile/map_'.$role->id, $role->localname, '', $role->shortname);
}
public function config_read($name) {
$value = parent::config_read($name);
if (is_null($value)) {
// In other settings NULL means we have to ask user for new value,
// here we just ignore missing role mappings.
$value = '';
}
return $value;
}
public function config_write($name, $value) {
if ($value === '') {
// We do not want empty values in config table,
// delete it instead.
$value = null;
}
return parent::config_write($name, $value);
}
}
+229
View File
@@ -0,0 +1,229 @@
<?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_flatfile.
*
* @package enrol_flatfile
* @category privacy
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_flatfile\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\context;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\userlist;
use core_privacy\local\request\writer;
use core_privacy\local\request\transform;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for enrol_flatfile 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\provider,
\core_privacy\local\request\plugin\provider,
\core_privacy\local\request\core_userlist_provider {
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection): collection {
return $collection->add_database_table('enrol_flatfile', [
'action' => 'privacy:metadata:enrol_flatfile:action',
'roleid' => 'privacy:metadata:enrol_flatfile:roleid',
'userid' => 'privacy:metadata:enrol_flatfile:userid',
'courseid' => 'privacy:metadata:enrol_flatfile:courseid',
'timestart' => 'privacy:metadata:enrol_flatfile:timestart',
'timeend' => 'privacy:metadata:enrol_flatfile:timeend',
'timemodified' => 'privacy:metadata:enrol_flatfile:timemodified'
], 'privacy:metadata:enrol_flatfile');
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid): contextlist {
$sql = "SELECT c.id
FROM {enrol_flatfile} ef
JOIN {context} c ON c.contextlevel = ? AND c.instanceid = ef.courseid
WHERE ef.userid = ?";
$params = [CONTEXT_COURSE, $userid];
$contextlist = new contextlist();
$contextlist->set_component('enrol_flatfile');
return $contextlist->add_from_sql($sql, $params);
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();
if ($context->contextlevel != CONTEXT_COURSE) {
return;
}
$sql = "SELECT userid FROM {enrol_flatfile} WHERE courseid = ?";
$params = [$context->instanceid];
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
// Ensure all contexts are CONTEXT_COURSE.
$contexts = static::validate_contextlist_contexts($contextlist);
if (empty($contexts)) {
return;
}
// Get the context instance ids from the contexts. These are the course ids..
$contextinstanceids = array_map(function($context) {
return $context->instanceid;
}, $contexts);
$userid = $contextlist->get_user()->id;
// Now, we just need to fetch and format all entries corresponding to the contextids provided.
$sql = "SELECT ef.action, r.shortname, ef.courseid, ef.timestart, ef.timeend, ef.timemodified
FROM {enrol_flatfile} ef
JOIN {context} c ON c.contextlevel = :contextlevel AND c.instanceid = ef.courseid
JOIN {role} r ON r.id = ef.roleid
WHERE ef.userid = :userid";
$params = ['contextlevel' => CONTEXT_COURSE, 'userid' => $userid];
list($insql, $inparams) = $DB->get_in_or_equal($contextinstanceids, SQL_PARAMS_NAMED);
$sql .= " AND ef.courseid $insql";
$params = array_merge($params, $inparams);
$futureenrolments = $DB->get_recordset_sql($sql, $params);
$enrolmentdata = [];
foreach ($futureenrolments as $futureenrolment) {
// It's possible to have more than one future enrolment per course.
$futureenrolment->timestart = transform::datetime($futureenrolment->timestart);
$futureenrolment->timeend = transform::datetime($futureenrolment->timeend);
$futureenrolment->timemodified = transform::datetime($futureenrolment->timemodified);
$enrolmentdata[$futureenrolment->courseid][] = $futureenrolment;
}
$futureenrolments->close();
// And finally, write out the data to the relevant course contexts.
$subcontext = \core_enrol\privacy\provider::get_subcontext([get_string('pluginname', 'enrol_flatfile')]);
foreach ($enrolmentdata as $courseid => $enrolments) {
$data = (object) [
'pendingenrolments' => $enrolments,
];
writer::with_context(\context_course::instance($courseid))->export_data($subcontext, $data);
}
}
/**
* Delete all data for all users in the specified context.
*
* @param \context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
if ($context->contextlevel != CONTEXT_COURSE) {
return;
}
global $DB;
$DB->delete_records('enrol_flatfile', ['courseid' => $context->instanceid]);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
// Only delete data from contexts which are at the CONTEXT_COURSE contextlevel.
$contexts = self::validate_contextlist_contexts($contextlist);
if (empty($contexts)) {
return;
}
// Get the course ids based on the provided contexts.
$contextinstanceids = array_map(function($context) {
return $context->instanceid;
}, $contextlist->get_contexts());
global $DB;
$user = $contextlist->get_user();
list($insql, $inparams) = $DB->get_in_or_equal($contextinstanceids, SQL_PARAMS_NAMED);
$params = array_merge(['userid' => $user->id], $inparams);
$sql = "userid = :userid AND courseid $insql";
$DB->delete_records_select('enrol_flatfile', $sql, $params);
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
global $DB;
$context = $userlist->get_context();
if ($context->contextlevel != CONTEXT_COURSE) {
return;
}
$userids = $userlist->get_userids();
list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params = array_merge(['courseid' => $context->instanceid], $inparams);
$sql = "courseid = :courseid AND userid $insql";
$DB->delete_records_select('enrol_flatfile', $sql, $params);
}
/**
* Simple sanity check on the contextlist contexts, making sure they're of CONTEXT_COURSE contextlevel.
*
* @param approved_contextlist $contextlist
* @return array the array of contexts filtered to only include those of CONTEXT_COURSE contextlevel.
*/
protected static function validate_contextlist_contexts(approved_contextlist $contextlist) {
return array_reduce($contextlist->get_contexts(), function($carry, $context) {
if ($context->contextlevel == CONTEXT_COURSE) {
$carry[] = $context;
}
return $carry;
}, []);
}
}
@@ -0,0 +1,66 @@
<?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/>.
/**
* Scheduled task for processing flatfile enrolments.
*
* @package enrol_flatfile
* @copyright 2014 Troy Williams
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_flatfile\task;
defined('MOODLE_INTERNAL') || die;
/**
* Simple task to run sync enrolments.
*
* @copyright 2014 Troy Williams
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class flatfile_sync_task extends \core\task\scheduled_task {
/**
* Get a descriptive name for this task (shown to admins).
*
* @return string
*/
public function get_name() {
return get_string('flatfilesync', 'enrol_flatfile');
}
/**
* Do the job.
* Throw exceptions on errors (the job will be retried).
*/
public function execute() {
global $CFG;
require_once($CFG->dirroot . '/enrol/flatfile/lib.php');
if (!enrol_is_enabled('flatfile')) {
return;
}
// Instance of enrol_flatfile_plugin.
$plugin = enrol_get_plugin('flatfile');
$result = $plugin->sync(new \null_progress_trace());
return $result;
}
}
+89
View File
@@ -0,0 +1,89 @@
<?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/>.
/**
* Flatfile CLI tool.
*
* 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
*
* Update
*
* This plugin now has a enrolment sync scheduled task. Scheduled tasks were
* introduced in Moodle 2.7. It is possible to override the scheduled tasks
* configuration and run a single scheduled task immediately using the
* admin/cli/scheduled_task.php script. This is the recommended
* method to use for immediate enrollment synchronisation.
*
* Usage help:
* $ php admin/cli/scheduled_task.php -h
*
* Execute task:
* $ sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php /
* --execute=\\enrol_flatfile\\task\\flatfile_sync_task
*
* @package enrol_flatfile
* @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 =
"Process flat file enrolments, update expiration 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/flatfile/cli/sync.php
";
echo $help;
die;
}
if (!enrol_is_enabled('flatfile')) {
cli_error('enrol_flatfile plugin is disabled, synchronisation stopped', 2);
}
/** @var $plugin enrol_flatfile_plugin */
$plugin = enrol_get_plugin('flatfile');
if (empty($options['verbose'])) {
$trace = new null_progress_trace();
} else {
$trace = new text_progress_trace();
}
$result = $plugin->sync($trace);
exit($result);
+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/>.
/**
* Capabilities for manual enrolment plugin.
*
* @package enrol_flatfile
* @copyright 2012 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(
/* Manage enrolments of users - requires allowmodifications enabled. */
'enrol/flatfile:manage' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
)
),
/* Unenrol anybody (including self) - requires allowmodifications enabled */
'enrol/flatfile:unenrol' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
)
),
);
+35
View File
@@ -0,0 +1,35 @@
<?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/>.
/**
* Flatfile enrolment plugin installation.
*
* @package enrol_flatfile
* @copyright 2013 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_flatfile_install() {
global $CFG, $DB;
// Flatfile role mappings are empty by default now.
$roles = get_all_roles();
foreach ($roles as $role) {
set_config('map_'.$role->id, $role->shortname, 'enrol_flatfile');
}
}
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="enrol/flatfile/db" VERSION="20120122" COMMENT="XMLDB file for Moodle enrol/flatfile"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="enrol_flatfile" COMMENT="enrol_flatfile table retrofitted from MySQL">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="action" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="roleid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timestart" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timeend" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="id" TYPE="primary" FIELDS="id" COMMENT="primary key"/>
<KEY NAME="courseid-id" TYPE="foreign" FIELDS="courseid" REFTABLE="course" REFFIELDS="id"/>
<KEY NAME="userid-id" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
<KEY NAME="roleid-id" TYPE="foreign" FIELDS="roleid" REFTABLE="role" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
+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 (types of message sent) for the PayPal enrolment plugin.
*
* @package enrol_flatfile
* @copyright 2012 Andrew Davis
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$messageproviders = array(
'flatfile_enrolment' => [
'defaults' => [
'popup' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED,
'email' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED,
],
],
);
+37
View File
@@ -0,0 +1,37 @@
<?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/>.
/**
* Definition of flatfile enrolment scheduled tasks.
*
* @package enrol_flatfile
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$tasks = array(
array(
'classname' => '\enrol_flatfile\task\flatfile_sync_task',
'blocking' => 0,
'minute' => '15',
'hour' => '*',
'day' => '*',
'dayofweek' => '*',
'month' => '*'
)
);
+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/>.
/**
* Keeps track of upgrades to the enrol_flatfile plugin
*
* @package enrol_flatfile
* @copyright 2010 Aparup Banerjee <aparup@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
function xmldb_enrol_flatfile_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;
}
+6
View File
@@ -0,0 +1,6 @@
add, student, 5, CF101
add, teacher, 6, CF101
add, teacheredit, 7, CF101
del, student, 8, CF101
del, student, 17, CF101
add, student, 21, CF101, 1091115000, 1091215000
+72
View File
@@ -0,0 +1,72 @@
<?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_flatfile', language 'en'.
*
* @package enrol_flatfile
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['encoding'] = 'File encoding';
$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['filelockedmail'] = 'The text file you are using for file-based enrolments ({$a}) can not be deleted by the cron process. This usually means the permissions are wrong on it. Please fix the permissions so that Moodle can delete the file, otherwise it might be processed repeatedly.';
$string['filelockedmailsubject'] = 'Important error: Enrolment file';
$string['flatfile:manage'] = 'Manage user enrolments manually';
$string['flatfile:unenrol'] = 'Unenrol users from the course manually';
$string['flatfileenrolments'] = 'Flat file (CSV) enrolments';
$string['flatfilesync'] = 'Flat file enrolment sync';
$string['location'] = 'File location';
$string['location_desc'] = 'Specify full path to the enrolment file. The file is automatically deleted after processing.';
$string['notifyadmin'] = 'Notify administrator';
$string['notifyenrolled'] = 'Notify enrolled users';
$string['notifyenroller'] = 'Notify user responsible for enrolments';
$string['messageprovider:flatfile_enrolment'] = 'Flat file enrolment messages';
$string['mapping'] = 'Flat file role mapping';
$string['pluginname'] = 'Flat file (CSV)';
$string['pluginname_desc'] = 'This method will repeatedly check for and process a specially-formatted text file in the location that you specify.
The file is a comma separated file assumed to have four or six fields per line:
operation, role, user idnumber, course idnumber [, starttime [, endtime]]
where:
* operation - add | del
* role - student | teacher | teacheredit
* user idnumber - idnumber in the user table NB not id
* course idnumber - idnumber in the course table NB not id
* starttime - start time (in seconds since epoch) - optional
* endtime - end time (in seconds since epoch) - optional
It could look something like this:
<pre class="informationbox">
add, student, 5, CF101
add, teacher, 6, CF101
add, teacheredit, 7, CF101
del, student, 8, CF101
del, student, 17, CF101
add, student, 21, CF101, 1091115000, 1091215000
</pre>';
$string['privacy:metadata:enrol_flatfile'] = 'The Flat file (CSV) enrolment plugin may store personal data relating to future enrolments in the enrol_flatfile table.';
$string['privacy:metadata:enrol_flatfile:action'] = 'The enrolment action expected on the given date';
$string['privacy:metadata:enrol_flatfile:courseid'] = 'The course ID to which the enrolment relates';
$string['privacy:metadata:enrol_flatfile:roleid'] = 'The ID of the role to be assigned or unassigned';
$string['privacy:metadata:enrol_flatfile:timestart'] = 'The time when the enrolment starts';
$string['privacy:metadata:enrol_flatfile:timeend'] = 'The time when the enrolment ends';
$string['privacy:metadata:enrol_flatfile:timemodified'] = 'The time when the enrolment is modified';
$string['privacy:metadata:enrol_flatfile:userid'] = 'The ID of the user to which the role assignment relates';
+696
View File
@@ -0,0 +1,696 @@
<?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/>.
/**
* Flatfile enrolment plugin.
*
* This plugin lets the user specify a "flatfile" (CSV) containing enrolment information.
* On a regular cron cycle, the specified file is parsed and then deleted.
*
* @package enrol_flatfile
* @copyright 2010 Eugene Venter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Flatfile enrolment plugin implementation.
*
* Comma separated file assumed to have four or six fields per line:
* operation, role, idnumber(user), idnumber(course) [, starttime [, endtime]]
* where:
* operation = add | del
* role = student | teacher | teacheredit
* idnumber(user) = idnumber in the user table NB not id
* idnumber(course) = idnumber in the course table NB not id
* starttime = start time (in seconds since epoch) - optional
* endtime = end time (in seconds since epoch) - optional
*
* @author Eugene Venter - based on code by Petr Skoda, Martin Dougiamas, Martin Langhoff and others
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_flatfile_plugin extends enrol_plugin {
protected $lasternoller = null;
protected $lasternollercourseid = 0;
/**
* Does this plugin assign protected roles are can they be manually removed?
* @return bool - false means anybody may tweak roles, it does not use itemid and component when assigning roles
*/
public function roles_protected() {
return false;
}
/**
* Does this plugin allow manual unenrolment of all users?
* All plugins allowing this must implement 'enrol/xxx:unenrol' capability
*
* @param stdClass $instance course enrol instance
* @return bool - true means user with 'enrol/xxx:unenrol' may unenrol others freely, false means nobody may touch user_enrolments
*/
public function allow_unenrol(stdClass $instance) {
return true;
}
/**
* Does this plugin allow manual unenrolment of a specific user?
* All plugins allowing this must implement 'enrol/xxx:unenrol' capability
*
* This is useful especially for synchronisation plugins that
* do suspend instead of full unenrolment.
*
* @param stdClass $instance course enrol instance
* @param stdClass $ue record from user_enrolments table, specifies user
*
* @return bool - true means user with 'enrol/xxx:unenrol' may unenrol this user, false means nobody may touch this user enrolment
*/
public function allow_unenrol_user(stdClass $instance, stdClass $ue) {
return true;
}
/**
* Does this plugin allow manual changes in user_enrolments table?
*
* All plugins allowing this must implement 'enrol/xxx:manage' capability
*
* @param stdClass $instance course enrol instance
* @return bool - true means it is possible to change enrol period and status in user_enrolments table
*/
public function allow_manage(stdClass $instance) {
return true;
}
/**
* 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/flatfile:manage', $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/flatfile:manage', $context);
}
/**
* Enrol user into course via enrol instance.
*
* @param stdClass $instance
* @param int $userid
* @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 void
*/
public function enrol_user(stdClass $instance, $userid, $roleid = null, $timestart = 0, $timeend = 0, $status = null, $recovergrades = null) {
parent::enrol_user($instance, $userid, null, $timestart, $timeend, $status, $recovergrades);
if ($roleid) {
$context = context_course::instance($instance->courseid, MUST_EXIST);
role_assign($roleid, $userid, $context->id, 'enrol_'.$this->get_name(), $instance->id);
}
}
/**
* Execute synchronisation.
* @param progress_trace
* @return int exit code, 0 means ok, 2 means plugin disabled
*/
public function sync(progress_trace $trace) {
if (!enrol_is_enabled('flatfile')) {
return 2;
}
$mailadmins = $this->get_config('mailadmins', 0);
if ($mailadmins) {
$buffer = new progress_trace_buffer(new text_progress_trace(), false);
$trace = new combined_progress_trace(array($trace, $buffer));
}
$processed = false;
$processed = $this->process_file($trace) || $processed;
$processed = $this->process_buffer($trace) || $processed;
$processed = $this->process_expirations($trace) || $processed;
if ($processed and $mailadmins) {
if ($log = $buffer->get_buffer()) {
$eventdata = new \core\message\message();
$eventdata->courseid = SITEID;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_flatfile';
$eventdata->name = 'flatfile_enrolment';
$eventdata->userfrom = get_admin();
$eventdata->userto = get_admin();
$eventdata->subject = 'Flatfile Enrolment Log';
$eventdata->fullmessage = $log;
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
}
$buffer->reset_buffer();
}
return 0;
}
/**
* Sorry, we do not want to show paths in cron output.
*
* @param string $filepath
* @return string
*/
protected function obfuscate_filepath($filepath) {
global $CFG;
if (strpos($filepath, $CFG->dataroot.'/') === 0 or strpos($filepath, $CFG->dataroot.'\\') === 0) {
$disclosefile = '$CFG->dataroot'.substr($filepath, strlen($CFG->dataroot));
} else if (strpos($filepath, $CFG->dirroot.'/') === 0 or strpos($filepath, $CFG->dirroot.'\\') === 0) {
$disclosefile = '$CFG->dirroot'.substr($filepath, strlen($CFG->dirroot));
} else {
$disclosefile = basename($filepath);
}
return $disclosefile;
}
/**
* Process flatfile.
* @param progress_trace $trace
* @return bool true if any data processed, false if not
*/
protected function process_file(progress_trace $trace) {
global $CFG, $DB;
// We may need more memory here.
core_php_time_limit::raise();
raise_memory_limit(MEMORY_HUGE);
$filelocation = $this->get_config('location');
if (empty($filelocation)) {
// Default legacy location.
$filelocation = "$CFG->dataroot/1/enrolments.txt";
}
$disclosefile = $this->obfuscate_filepath($filelocation);
if (!file_exists($filelocation)) {
$trace->output("Flatfile enrolments file not found: $disclosefile");
$trace->finished();
return false;
}
$trace->output("Processing flat file enrolments from: $disclosefile ...");
$content = file_get_contents($filelocation);
if ($content !== false) {
$rolemap = $this->get_role_map($trace);
$content = core_text::convert($content, $this->get_config('encoding', 'utf-8'), 'utf-8');
$content = str_replace("\r", '', $content);
$content = explode("\n", $content);
$line = 0;
foreach($content as $fields) {
$line++;
if (trim($fields) === '') {
// Empty lines are ignored.
continue;
}
// Deal with different separators.
if (strpos($fields, ',') !== false) {
$fields = explode(',', $fields);
} else {
$fields = explode(';', $fields);
}
// If a line is incorrectly formatted ie does not have 4 comma separated fields then ignore it.
if (count($fields) < 4 or count($fields) > 6) {
$trace->output("Line incorrectly formatted - ignoring $line", 1);
continue;
}
$fields[0] = trim(core_text::strtolower($fields[0]));
$fields[1] = trim(core_text::strtolower($fields[1]));
$fields[2] = trim($fields[2]);
$fields[3] = trim($fields[3]);
$fields[4] = isset($fields[4]) ? (int)trim($fields[4]) : 0;
$fields[5] = isset($fields[5]) ? (int)trim($fields[5]) : 0;
// Deal with quoted values - all or nothing, we need to support "' in idnumbers, sorry.
if (strpos($fields[0], "'") === 0) {
foreach ($fields as $k=>$v) {
$fields[$k] = trim($v, "'");
}
} else if (strpos($fields[0], '"') === 0) {
foreach ($fields as $k=>$v) {
$fields[$k] = trim($v, '"');
}
}
$trace->output("$line: $fields[0], $fields[1], $fields[2], $fields[3], $fields[4], $fields[5]", 1);
// Check correct formatting of operation field.
if ($fields[0] !== "add" and $fields[0] !== "del") {
$trace->output("Unknown operation in field 1 - ignoring line $line", 1);
continue;
}
// Check correct formatting of role field.
if (!isset($rolemap[$fields[1]])) {
$trace->output("Unknown role in field2 - ignoring line $line", 1);
continue;
}
$roleid = $rolemap[$fields[1]];
if (empty($fields[2]) or !$user = $DB->get_record("user", array("idnumber"=>$fields[2], 'deleted'=>0))) {
$trace->output("Unknown user idnumber or deleted user in field 3 - ignoring line $line", 1);
continue;
}
if (!$course = $DB->get_record("course", array("idnumber"=>$fields[3]))) {
$trace->output("Unknown course idnumber in field 4 - ignoring line $line", 1);
continue;
}
if ($fields[4] > $fields[5] and $fields[5] != 0) {
$trace->output("Start time was later than end time - ignoring line $line", 1);
continue;
}
$this->process_records($trace, $fields[0], $roleid, $user, $course, $fields[4], $fields[5]);
}
unset($content);
}
if (!unlink($filelocation)) {
$eventdata = new \core\message\message();
$eventdata->courseid = SITEID;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_flatfile';
$eventdata->name = 'flatfile_enrolment';
$eventdata->userfrom = get_admin();
$eventdata->userto = get_admin();
$eventdata->subject = get_string('filelockedmailsubject', 'enrol_flatfile');
$eventdata->fullmessage = get_string('filelockedmail', 'enrol_flatfile', $filelocation);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
$trace->output("Error deleting enrolment file: $disclosefile", 1);
} else {
$trace->output("Deleted enrolment file", 1);
}
$trace->output("...finished enrolment file processing.");
$trace->finished();
return true;
}
/**
* Process any future enrollments stored in the buffer.
* @param progress_trace $trace
* @return bool true if any data processed, false if not
*/
protected function process_buffer(progress_trace $trace) {
global $DB;
if (!$future_enrols = $DB->get_records_select('enrol_flatfile', "timestart < ?", array(time()))) {
$trace->output("No enrolments to be processed in flatfile buffer");
$trace->finished();
return false;
}
$trace->output("Starting processing of flatfile buffer");
foreach($future_enrols as $en) {
$user = $DB->get_record('user', array('id'=>$en->userid));
$course = $DB->get_record('course', array('id'=>$en->courseid));
if ($user and $course) {
$trace->output("buffer: $en->action $en->roleid $user->id $course->id $en->timestart $en->timeend", 1);
$this->process_records($trace, $en->action, $en->roleid, $user, $course, $en->timestart, $en->timeend, false);
}
$DB->delete_records('enrol_flatfile', array('id'=>$en->id));
}
$trace->output("Finished processing of flatfile buffer");
$trace->finished();
return true;
}
/**
* Process user enrolment line.
*
* @param progress_trace $trace
* @param string $action
* @param int $roleid
* @param stdClass $user
* @param stdClass $course
* @param int $timestart
* @param int $timeend
* @param bool $buffer_if_future
*/
protected function process_records(progress_trace $trace, $action, $roleid, $user, $course, $timestart, $timeend, $buffer_if_future = true) {
global $CFG, $DB;
// Check if timestart is for future processing.
if ($timestart > time() and $buffer_if_future) {
// Populate into enrol_flatfile table as a future role to be assigned by cron.
// Note: since 2.0 future enrolments do not cause problems if you disable guest access.
$future_en = new stdClass();
$future_en->action = $action;
$future_en->roleid = $roleid;
$future_en->userid = $user->id;
$future_en->courseid = $course->id;
$future_en->timestart = $timestart;
$future_en->timeend = $timeend;
$future_en->timemodified = time();
$DB->insert_record('enrol_flatfile', $future_en);
$trace->output("User $user->id will be enrolled later into course $course->id using role $roleid ($timestart, $timeend)", 1);
return;
}
$context = context_course::instance($course->id);
if ($action === 'add') {
// Clear the buffer just in case there were some future enrolments.
$DB->delete_records('enrol_flatfile', array('userid'=>$user->id, 'courseid'=>$course->id, 'roleid'=>$roleid));
$instance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'flatfile'));
if (empty($instance)) {
// Only add an enrol instance to the course if non-existent.
$enrolid = $this->add_instance($course);
$instance = $DB->get_record('enrol', array('id' => $enrolid));
}
$notify = false;
if ($ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$user->id))) {
// Update only.
$this->update_user_enrol($instance, $user->id, ENROL_USER_ACTIVE, $timestart, $timeend);
if (!$DB->record_exists('role_assignments', array('contextid'=>$context->id, 'roleid'=>$roleid, 'userid'=>$user->id, 'component'=>'enrol_flatfile', 'itemid'=>$instance->id))) {
role_assign($roleid, $user->id, $context->id, 'enrol_flatfile', $instance->id);
}
$trace->output("User $user->id enrolment updated in course $course->id using role $roleid ($timestart, $timeend)", 1);
} else {
// Enrol the user with this plugin instance.
$this->enrol_user($instance, $user->id, $roleid, $timestart, $timeend);
$trace->output("User $user->id enrolled in course $course->id using role $roleid ($timestart, $timeend)", 1);
$notify = true;
}
if ($notify and $this->get_config('mailstudents')) {
$oldforcelang = force_current_language($user->lang);
// Send welcome notification to enrolled users.
$a = new stdClass();
$a->coursename = format_string($course->fullname, true, array('context' => $context));
$a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id&amp;course=$course->id";
$subject = get_string('enrolmentnew', 'enrol', format_string($course->shortname, true, array('context' => $context)));
$eventdata = new \core\message\message();
$eventdata->courseid = $course->id;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_flatfile';
$eventdata->name = 'flatfile_enrolment';
$eventdata->userfrom = $this->get_enroller($course->id);
$eventdata->userto = $user;
$eventdata->subject = $subject;
$eventdata->fullmessage = get_string('welcometocoursetext', '', $a);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
if (message_send($eventdata)) {
$trace->output("Notified enrolled user", 1);
} else {
$trace->output("Failed to notify enrolled user", 1);
}
force_current_language($oldforcelang);
}
if ($notify and $this->get_config('mailteachers', 0)) {
// Notify person responsible for enrolments.
$enroller = $this->get_enroller($course->id);
$oldforcelang = force_current_language($enroller->lang);
$a = new stdClass();
$a->course = format_string($course->fullname, true, array('context' => $context));
$a->user = fullname($user);
$subject = get_string('enrolmentnew', 'enrol', format_string($course->shortname, true, array('context' => $context)));
$eventdata = new \core\message\message();
$eventdata->courseid = $course->id;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_flatfile';
$eventdata->name = 'flatfile_enrolment';
$eventdata->userfrom = get_admin();
$eventdata->userto = $enroller;
$eventdata->subject = $subject;
$eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
if (message_send($eventdata)) {
$trace->output("Notified enroller {$eventdata->userto->id}", 1);
} else {
$trace->output("Failed to notify enroller {$eventdata->userto->id}", 1);
}
force_current_language($oldforcelang);
}
return;
} else if ($action === 'del') {
// Clear the buffer just in case there were some future enrolments.
$DB->delete_records('enrol_flatfile', array('userid'=>$user->id, 'courseid'=>$course->id, 'roleid'=>$roleid));
$action = $this->get_config('unenrolaction');
if ($action == ENROL_EXT_REMOVED_KEEP) {
$trace->output("del action is ignored", 1);
return;
}
// Loops through all enrolment methods, try to unenrol if roleid somehow matches.
$instances = $DB->get_records('enrol', array('courseid' => $course->id));
$unenrolled = false;
foreach ($instances as $instance) {
if (!$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$user->id))) {
continue;
}
if ($instance->enrol === 'flatfile') {
$plugin = $this;
} else {
if (!enrol_is_enabled($instance->enrol)) {
continue;
}
if (!$plugin = enrol_get_plugin($instance->enrol)) {
continue;
}
if (!$plugin->allow_unenrol_user($instance, $ue)) {
continue;
}
}
// For some reason the del action includes a role name, this complicates everything.
$componentroles = array();
$manualroles = array();
$ras = $DB->get_records('role_assignments', array('userid'=>$user->id, 'contextid'=>$context->id));
foreach ($ras as $ra) {
if ($ra->component === '') {
$manualroles[$ra->roleid] = $ra->roleid;
} else if ($ra->component === 'enrol_'.$instance->enrol and $ra->itemid == $instance->id) {
$componentroles[$ra->roleid] = $ra->roleid;
}
}
if ($componentroles and !isset($componentroles[$roleid])) {
// Do not unenrol using this method, user has some other protected role!
continue;
} else if (empty($ras)) {
// If user does not have any roles then let's just suspend as many methods as possible.
} else if (!$plugin->roles_protected()) {
if (!$componentroles and $manualroles and !isset($manualroles[$roleid])) {
// Most likely we want to keep users enrolled because they have some other course roles.
continue;
}
}
if ($action == ENROL_EXT_REMOVED_UNENROL) {
$unenrolled = true;
if (!$plugin->roles_protected()) {
role_unassign_all(array('contextid'=>$context->id, 'userid'=>$user->id, 'roleid'=>$roleid, 'component'=>'', 'itemid'=>0), true);
}
$plugin->unenrol_user($instance, $user->id);
$trace->output("User $user->id was unenrolled from course $course->id (enrol_$instance->enrol)", 1);
} else if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
if ($plugin->allow_manage($instance)) {
if ($ue->status == ENROL_USER_ACTIVE) {
$unenrolled = true;
$plugin->update_user_enrol($instance, $user->id, ENROL_USER_SUSPENDED);
if (!$plugin->roles_protected()) {
role_unassign_all(array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'enrol_'.$instance->enrol, 'itemid'=>$instance->id), true);
role_unassign_all(array('contextid'=>$context->id, 'userid'=>$user->id, 'roleid'=>$roleid, 'component'=>'', 'itemid'=>0), true);
}
$trace->output("User $user->id enrolment was suspended in course $course->id (enrol_$instance->enrol)", 1);
}
}
}
}
if (!$unenrolled) {
if (0 == $DB->count_records('role_assignments', array('userid'=>$user->id, 'contextid'=>$context->id))) {
role_unassign_all(array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'', 'itemid'=>0), true);
}
$trace->output("User $user->id (with role $roleid) not unenrolled from course $course->id", 1);
}
return;
}
}
/**
* Returns the user who is responsible for flatfile enrolments in given curse.
*
* Usually it is the first editing teacher - the person with "highest authority"
* as defined by sort_by_roleassignment_authority() having 'enrol/flatfile:manage'
* or 'moodle/role:assign' capability.
*
* @param int $courseid enrolment instance id
* @return stdClass user record
*/
protected function get_enroller($courseid) {
if ($this->lasternollercourseid == $courseid and $this->lasternoller) {
return $this->lasternoller;
}
$context = context_course::instance($courseid);
$users = get_enrolled_users($context, 'enrol/flatfile:manage');
if (!$users) {
$users = get_enrolled_users($context, 'moodle/role:assign');
}
if ($users) {
$users = sort_by_roleassignment_authority($users, $context);
$this->lasternoller = reset($users);
unset($users);
} else {
$this->lasternoller = get_admin();
}
$this->lasternollercourseid == $courseid;
return $this->lasternoller;
}
/**
* Returns a mapping of ims roles to role ids.
*
* @param progress_trace $trace
* @return array imsrolename=>roleid
*/
protected function get_role_map(progress_trace $trace) {
global $DB;
// Get all roles.
$rolemap = array();
$roles = $DB->get_records('role', null, '', 'id, name, shortname');
foreach ($roles as $id=>$role) {
$alias = $this->get_config('map_'.$id, $role->shortname, '');
$alias = trim(core_text::strtolower($alias));
if ($alias === '') {
// Either not configured yet or somebody wants to skip these intentionally.
continue;
}
if (isset($rolemap[$alias])) {
$trace->output("Duplicate role alias $alias detected!");
} else {
$rolemap[$alias] = $id;
}
}
return $rolemap;
}
/**
* 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;
if ($instance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>$this->get_name()))) {
$instanceid = $instance->id;
} else {
$instanceid = $this->add_instance($course);
}
$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) {
$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) {
role_assign($roleid, $userid, $contextid, 'enrol_'.$instance->enrol, $instance->id);
}
}
+71
View File
@@ -0,0 +1,71 @@
<?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/>.
/**
* Flatfile enrolments plugin settings and presets.
*
* @package enrol_flatfile
* @copyright 2010 Eugene Venter
* @author Eugene Venter - based on code by Petr Skoda and others
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/adminlib.php');
if ($ADMIN->fulltree) {
//--- general settings -----------------------------------------------------------------------------------
$settings->add(new admin_setting_heading('enrol_flatfile_settings', '', get_string('pluginname_desc', 'enrol_flatfile')));
$settings->add(new admin_setting_configfile('enrol_flatfile/location', get_string('location', 'enrol_flatfile'), get_string('location_desc', 'enrol_flatfile'), ''));
$options = core_text::get_encodings();
$settings->add(new admin_setting_configselect('enrol_flatfile/encoding', get_string('encoding', 'enrol_flatfile'), '', 'UTF-8', $options));
$settings->add(new admin_setting_configcheckbox('enrol_flatfile/mailstudents', get_string('notifyenrolled', 'enrol_flatfile'), '', 0));
$settings->add(new admin_setting_configcheckbox('enrol_flatfile/mailteachers', get_string('notifyenroller', 'enrol_flatfile'), '', 0));
$settings->add(new admin_setting_configcheckbox('enrol_flatfile/mailadmins', get_string('notifyadmin', 'enrol_flatfile'), '', 0));
$options = array(ENROL_EXT_REMOVED_UNENROL => get_string('extremovedunenrol', 'enrol'),
ENROL_EXT_REMOVED_KEEP => get_string('extremovedkeep', 'enrol'),
ENROL_EXT_REMOVED_SUSPENDNOROLES => get_string('extremovedsuspendnoroles', 'enrol'));
$settings->add(new admin_setting_configselect('enrol_flatfile/unenrolaction', get_string('extremovedaction', 'enrol'), get_string('extremovedaction_help', 'enrol'), ENROL_EXT_REMOVED_SUSPENDNOROLES, $options));
// Note: let's reuse the ext sync constants and strings here, internally it is very similar,
// it describes what should happen when users are not supposed to be enrolled any more.
$options = array(
ENROL_EXT_REMOVED_KEEP => get_string('extremovedkeep', 'enrol'),
ENROL_EXT_REMOVED_SUSPENDNOROLES => get_string('extremovedsuspendnoroles', 'enrol'),
ENROL_EXT_REMOVED_UNENROL => get_string('extremovedunenrol', 'enrol'),
);
$settings->add(new admin_setting_configselect('enrol_flatfile/expiredaction', get_string('expiredaction', 'enrol_flatfile'), get_string('expiredaction_help', 'enrol_flatfile'), ENROL_EXT_REMOVED_SUSPENDNOROLES, $options));
//--- mapping -------------------------------------------------------------------------------------------
if (!during_initial_install()) {
$settings->add(new admin_setting_heading('enrol_flatfile_mapping', get_string('mapping', 'enrol_flatfile'), ''));
$roles = role_fix_names(get_all_roles());
foreach ($roles as $role) {
$settings->add(new enrol_flatfile_role_setting($role));
}
unset($roles);
}
}
+555
View File
@@ -0,0 +1,555 @@
<?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/>.
/**
* flatfile enrolment sync tests.
*
* @package enrol_flatfile
* @category test
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_flatfile;
use enrol_flatfile\task\flatfile_sync_task;
/**
* flatfile enrolment sync tests.
*
* @package enrol_flatfile
* @category test
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class flatfile_test extends \advanced_testcase {
protected function enable_plugin() {
$enabled = enrol_get_plugins(true);
$enabled['flatfile'] = true;
$enabled = array_keys($enabled);
set_config('enrol_plugins_enabled', implode(',', $enabled));
}
protected function disable_plugin() {
$enabled = enrol_get_plugins(true);
unset($enabled['flatfile']);
$enabled = array_keys($enabled);
set_config('enrol_plugins_enabled', implode(',', $enabled));
}
public function test_basics(): void {
$this->assertFalse(enrol_is_enabled('flatfile'));
$plugin = enrol_get_plugin('flatfile');
$this->assertInstanceOf('enrol_flatfile_plugin', $plugin);
$this->assertEquals(ENROL_EXT_REMOVED_SUSPENDNOROLES, get_config('enrol_flatfile', 'expiredaction'));
}
public function test_sync_nothing(): void {
$this->resetAfterTest();
$this->disable_plugin();
$flatfileplugin = enrol_get_plugin('flatfile');
// Just make sure the sync does not throw any errors when nothing to do.
$flatfileplugin->sync(new \null_progress_trace());
$this->enable_plugin();
$flatfileplugin->sync(new \null_progress_trace());
}
public function test_sync(): void {
global $CFG, $DB;
$this->resetAfterTest();
/** @var \enrol_flatfile_plugin $flatfileplugin */
$flatfileplugin = enrol_get_plugin('flatfile');
/** @var \enrol_manual_plugin $manualplugin */
$manualplugin = enrol_get_plugin('manual');
$this->assertNotEmpty($manualplugin);
$trace = new \null_progress_trace();
$this->enable_plugin();
$file = "$CFG->dataroot/enrol.txt";
$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(array('idnumber'=>'u1'));
$user2 = $this->getDataGenerator()->create_user(array('idnumber'=>'u2'));
$user3 = $this->getDataGenerator()->create_user(array('idnumber'=>'u3'));
$user4 = $this->getDataGenerator()->create_user(array('idnumber'=>'čtvrtý'));
$user5 = $this->getDataGenerator()->create_user(array('idnumber'=>'u5'));
$user6 = $this->getDataGenerator()->create_user(array('idnumber'=>'u6'));
$user7 = $this->getDataGenerator()->create_user(array('idnumber'=>''));
$course1 = $this->getDataGenerator()->create_course(array('idnumber'=>'c1'));
$course2 = $this->getDataGenerator()->create_course(array('idnumber'=>'c2'));
$course3 = $this->getDataGenerator()->create_course(array('idnumber'=>'c3'));
$context1 = \context_course::instance($course1->id);
$context2 = \context_course::instance($course2->id);
$context3 = \context_course::instance($course3->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);
$maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
// Rename teacher role.
$flatfileplugin->set_config('map_'.$teacherrole->id, 'ucitel');
// Disable manager role.
$flatfileplugin->set_config('map_'.$managerrole->id, '');
// Set file location.
$flatfileplugin->set_config('location', $file);
$now = time();
$before = $now - 60;
$future = $now + 60*60*5;
$farfuture = $now + 60*60*24*5;
// Test add action.
$data ="'add','student','u1','c1'
\"add\" , \"ucitel\", u2 , c2
add,manager,u3,c1
add,student,čtvrtý,c2,$before
add,student,u5,c1,0,0,1
add,student,u5,c2,20,10
add,student,u6,c1,0,$future
add,student,u6,c2,$future,0
add,student,u6,c3,$future,$farfuture
add,student,,c2";
file_put_contents($file, $data);
$this->assertEquals(0, $DB->count_records('user_enrolments'));
$this->assertEquals(0, $DB->count_records('role_assignments'));
$this->assertEquals(0, $DB->count_records('enrol_flatfile'));
$this->assertTrue(file_exists($file));
$flatfileplugin->sync($trace);
$this->assertFalse(file_exists($file));
$this->assertEquals(4, $DB->count_records('user_enrolments'));
$this->assertEquals(4, $DB->count_records('role_assignments'));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user2->id, 'roleid'=>$teacherrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user4->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user6->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
// Test buffer.
$this->assertEquals(2, $DB->count_records('enrol_flatfile'));
$flatfileplugin->sync($trace);
$this->assertEquals(2, $DB->count_records('enrol_flatfile'));
$this->assertEquals(4, $DB->count_records('user_enrolments'));
$this->assertEquals(4, $DB->count_records('role_assignments'));
$DB->set_field('enrol_flatfile', 'timestart', time()-60, array('timestart'=>$future, 'timeend'=>0));
$flatfileplugin->sync($trace);
$this->assertEquals(1, $DB->count_records('enrol_flatfile'));
$this->assertEquals(5, $DB->count_records('user_enrolments'));
$this->assertEquals(5, $DB->count_records('role_assignments'));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user6->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('enrol_flatfile', array('userid'=>$user6->id, 'roleid'=>$studentrole->id, 'timeend'=>$farfuture)));
// Test encoding.
$data = "add;student;čtvrtý;c3";
$data = \core_text::convert($data, 'utf-8', 'iso-8859-2');
file_put_contents($file, $data);
$flatfileplugin->set_config('encoding', 'iso-8859-2');
$flatfileplugin->sync($trace);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertEquals(6, $DB->count_records('role_assignments'));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user4->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$flatfileplugin->set_config('encoding', 'UTF-8');
// Test unenrolling purges buffer.
$manualplugin->enrol_user($maninstance1, $user1->id, $teacherrole->id);
$manualplugin->enrol_user($maninstance3, $user5->id, $teacherrole->id);
$this->assertEquals(8, $DB->count_records('user_enrolments'));
$this->assertEquals(8, $DB->count_records('role_assignments'));
$this->assertEquals(1, $DB->count_records('enrol_flatfile'));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
$flatfileplugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
$data = "del,student,u1,c1\ndel,teacher,u6,c3";
file_put_contents($file, $data);
$flatfileplugin->sync($trace);
$this->assertEquals(8, $DB->count_records('user_enrolments'));
$this->assertEquals(8, $DB->count_records('role_assignments'));
$this->assertEquals(1, $DB->count_records('enrol_flatfile'));
$data = "del,student,u6,c3";
file_put_contents($file, $data);
$flatfileplugin->sync($trace);
$this->assertEquals(8, $DB->count_records('user_enrolments'));
$this->assertEquals(8, $DB->count_records('role_assignments'));
$this->assertEquals(0, $DB->count_records('enrol_flatfile'));
$flatfileplugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
$data = "
del,student,u1,c1
del,grrr,u5,c1
del,guest,u5,c2
del,student,u6,c2
del,ucitel,u5,c3";
file_put_contents($file, $data);
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user6->id, 'roleid'=>$studentrole->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user5->id, 'roleid'=>$teacherrole->id)));
$flatfileplugin->sync($trace);
$this->assertEquals(8, $DB->count_records('user_enrolments'));
$this->assertEquals(5, $DB->count_records('role_assignments'));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user6->id, 'roleid'=>$studentrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user5->id, 'roleid'=>$teacherrole->id)));
$flatfileplugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
$manualplugin->enrol_user($maninstance3, $user5->id, $teacherrole->id);
$data = "
add,student,u1,c1
add,student,u6,c2";
file_put_contents($file, $data);
$flatfileplugin->sync($trace);
$this->assertEquals(8, $DB->count_records('user_enrolments'));
$this->assertEquals(8, $DB->count_records('role_assignments'));
$this->assertEquals(0, $DB->count_records('enrol_flatfile'));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user6->id, 'roleid'=>$studentrole->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user5->id, 'roleid'=>$teacherrole->id)));
$this->assertTrue($DB->record_exists('user_enrolments', array('userid'=>$user5->id, 'enrolid'=>$maninstance3->id)));
$this->assertTrue($DB->record_exists('user_enrolments', array('userid'=>$user1->id, 'enrolid'=>$maninstance1->id)));
$data = "
del,student,u1,c1
del,grrr,u5,c1
del,guest,u5,c2
del,student,u6,c2
del,ucitel,u5,c3";
file_put_contents($file, $data);
$flatfileplugin->sync($trace);
$this->assertEquals(5, $DB->count_records('user_enrolments'));
$this->assertEquals(5, $DB->count_records('role_assignments'));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id, 'component'=>'enrol_flatfile')));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user6->id, 'roleid'=>$studentrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user5->id, 'roleid'=>$teacherrole->id)));
$this->assertFalse($DB->record_exists('user_enrolments', array('userid'=>$user5->id, 'enrolid'=>$maninstance3->id)));
$this->assertTrue($DB->record_exists('user_enrolments', array('userid'=>$user1->id, 'enrolid'=>$maninstance1->id)));
}
public function test_notification(): void {
global $CFG, $DB;
$this->resetAfterTest();
$this->preventResetByRollback();
/** @var \enrol_flatfile_plugin $flatfileplugin */
$flatfileplugin = enrol_get_plugin('flatfile');
/** @var \enrol_manual_plugin $manualplugin */
$manualplugin = enrol_get_plugin('manual');
$this->assertNotEmpty($manualplugin);
$this->enable_plugin();
$trace = new \progress_trace_buffer(new \text_progress_trace(), false);
$file = "$CFG->dataroot/enrol.txt";
$flatfileplugin->set_config('location', $file);
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->assertNotEmpty($studentrole);
$teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
$this->assertNotEmpty($teacherrole);
$user1 = $this->getDataGenerator()->create_user(array('idnumber'=>'u1'));
$user2 = $this->getDataGenerator()->create_user(array('idnumber'=>'u2'));
$user3 = $this->getDataGenerator()->create_user(array('idnumber'=>'u3'));
$admin = get_admin();
$course1 = $this->getDataGenerator()->create_course(array('idnumber'=>'c1'));
$course2 = $this->getDataGenerator()->create_course(array('idnumber'=>'c2'));
$context1 = \context_course::instance($course1->id);
$context2 = \context_course::instance($course2->id);
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$now = time();
$future = $now + 60*60*5;
$farfuture = $now + 60*60*24*5;
$manualplugin->enrol_user($maninstance1, $user3->id, $teacherrole->id);
$data =
"add,student,u1,c1
add,student,u2,c2
add,student,u2,c1,$future,$farfuture";
file_put_contents($file, $data);
$this->assertEquals(1, $DB->count_records('user_enrolments'));
$this->assertEquals(1, $DB->count_records('role_assignments'));
$this->assertEquals(0, $DB->count_records('enrol_flatfile'));
$flatfileplugin->set_config('mailadmins', 1);
$flatfileplugin->set_config('mailteachers', 1);
$flatfileplugin->set_config('mailstudents', 1);
$sink = $this->redirectMessages();
$flatfileplugin->sync($trace);
$this->assertEquals(3, $DB->count_records('user_enrolments'));
$this->assertEquals(3, $DB->count_records('role_assignments'));
$this->assertEquals(1, $DB->count_records('enrol_flatfile'));
$messages = $sink->get_messages();
$this->assertCount(5, $messages);
// Notify student from teacher.
$this->assertEquals($user1->id, $messages[0]->useridto);
$this->assertEquals($user3->id, $messages[0]->useridfrom);
// Notify teacher.
$this->assertEquals($user3->id, $messages[1]->useridto);
$this->assertEquals($admin->id, $messages[1]->useridfrom);
// Notify student when teacher not present.
$this->assertEquals($user2->id, $messages[2]->useridto);
$this->assertEquals($admin->id, $messages[2]->useridfrom);
// Notify admin when teacher not present.
$this->assertEquals($admin->id, $messages[3]->useridto);
$this->assertEquals($admin->id, $messages[3]->useridfrom);
// Sent report to admin from self.
$this->assertEquals($admin->id, $messages[4]->useridto);
$this->assertEquals($admin->id, $messages[4]->useridfrom);
}
public function test_expired(): void {
global $DB;
$this->resetAfterTest();
/** @var \enrol_flatfile_plugin $flatfileplugin */
$flatfileplugin = enrol_get_plugin('flatfile');
/** @var \enrol_manual_plugin $manualplugin */
$manualplugin = enrol_get_plugin('manual');
$this->assertNotEmpty($manualplugin);
$now = time();
$trace = new \null_progress_trace();
$this->enable_plugin();
// 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();
$context1 = \context_course::instance($course1->id);
$context2 = \context_course::instance($course2->id);
$data = array('roleid'=>$studentrole->id, 'courseid'=>$course1->id);
$id = $flatfileplugin->add_instance($course1, $data);
$instance1 = $DB->get_record('enrol', array('id'=>$id));
$data = array('roleid'=>$studentrole->id, 'courseid'=>$course2->id);
$id = $flatfileplugin->add_instance($course2, $data);
$instance2 = $DB->get_record('enrol', array('id'=>$id));
$data = array('roleid'=>$teacherrole->id, 'courseid'=>$course2->id);
$id = $flatfileplugin->add_instance($course2, $data);
$instance3 = $DB->get_record('enrol', array('id'=>$id));
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$manualplugin->enrol_user($maninstance1, $user3->id, $studentrole->id);
$this->assertEquals(1, $DB->count_records('user_enrolments'));
$this->assertEquals(1, $DB->count_records('role_assignments'));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$flatfileplugin->enrol_user($instance1, $user1->id, $studentrole->id);
$flatfileplugin->enrol_user($instance1, $user2->id, $studentrole->id);
$flatfileplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now-60);
$flatfileplugin->enrol_user($instance2, $user1->id, $studentrole->id, 0, 0);
$flatfileplugin->enrol_user($instance2, $user2->id, $studentrole->id, 0, $now-60*60);
$flatfileplugin->enrol_user($instance2, $user3->id, $studentrole->id, 0, $now+60*60);
$flatfileplugin->enrol_user($instance3, $user1->id, $teacherrole->id, $now-60*60*24*7, $now-60);
$flatfileplugin->enrol_user($instance3, $user4->id, $teacherrole->id);
role_assign($managerrole->id, $user3->id, $context1->id);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(10, $DB->count_records('role_assignments'));
$this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
// Execute tests.
$flatfileplugin->set_config('expiredaction', ENROL_EXT_REMOVED_KEEP);
$code = $flatfileplugin->sync($trace);
$this->assertSame(0, $code);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(10, $DB->count_records('role_assignments'));
$flatfileplugin->set_config('expiredaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
$flatfileplugin->sync($trace);
$this->assertEquals(9, $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)));
$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'=>$context2->id, 'userid'=>$user2->id, 'roleid'=>$studentrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id)));
$flatfileplugin->set_config('expiredaction', ENROL_EXT_REMOVED_UNENROL);
role_assign($studentrole->id, $user3->id, $context1->id, 'enrol_flatfile', $instance1->id);
role_assign($studentrole->id, $user2->id, $context2->id, 'enrol_flatfile', $instance2->id);
role_assign($teacherrole->id, $user1->id, $context2->id, 'enrol_flatfile', $instance3->id);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(10, $DB->count_records('role_assignments'));
$this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
$flatfileplugin->sync($trace);
$this->assertEquals(6, $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'=>$instance2->id, 'userid'=>$user2->id)));
$this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user1->id)));
$this->assertEquals(6, $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(0, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
}
/**
* Flatfile enrolment sync task test.
*/
public function test_flatfile_sync_task(): void {
global $CFG, $DB;
$this->resetAfterTest();
$flatfileplugin = enrol_get_plugin('flatfile');
$trace = new \null_progress_trace();
$this->enable_plugin();
$file = "$CFG->dataroot/enrol.txt";
$flatfileplugin->set_config('location', $file);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->assertNotEmpty($studentrole);
$user1 = $this->getDataGenerator()->create_user(array('idnumber' => 'u1'));
$course1 = $this->getDataGenerator()->create_course(array('idnumber' => 'c1'));
$context1 = \context_course::instance($course1->id);
$data =
"add,student,u1,c1";
file_put_contents($file, $data);
$task = new flatfile_sync_task;
$task->execute();
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid' => $studentrole->id)));
}
/**
* 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 = 'flatfile';
// Only enable the flatfile 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 student.
$student = $generator->create_user();
// Enrol the student to the course.
$generator->enrol_user($student->id, $course->id, 'student', $pluginname);
// Teachers don't have enrol/flatfile:manage and enrol/flatfile:unenrol capabilities by default.
// Login as admin for simplicity.
$this->setAdminUser();
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);
// Flatfile enrolment has 2 enrol actions for active users -- edit and unenrol.
$this->assertCount(2, $actions);
}
}
@@ -0,0 +1,312 @@
<?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 tests for enrol_flatfile.
*
* @package enrol_flatfile
* @category test
* @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_flatfile\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\metadata\collection;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\writer;
use enrol_flatfile\privacy\provider;
/**
* Privacy tests for enrol_flatfile.
*
* @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
/** @var \stdClass $user1 a test user.*/
protected $user1;
/** @var \stdClass $user2 a test user.*/
protected $user2;
/** @var \stdClass $user3 a test user.*/
protected $user3;
/** @var \stdClass $user4 a test user.*/
protected $user4;
/** @var \context $coursecontext1 a course context.*/
protected $coursecontext1;
/** @var \context $coursecontext2 a course context.*/
protected $coursecontext2;
/** @var \context $coursecontext3 a course context.*/
protected $coursecontext3;
/**
* Called before every test.
*/
public function setUp(): void {
$this->resetAfterTest(true);
}
/**
* Verify that get_metadata returns the database table mapping.
*/
public function test_get_metadata(): void {
$collection = new collection('enrol_flatfile');
$collection = provider::get_metadata($collection);
$collectiondata = $collection->get_collection();
$this->assertNotEmpty($collectiondata);
$this->assertInstanceOf(\core_privacy\local\metadata\types\database_table::class, $collectiondata[0]);
}
/**
* Verify that the relevant course contexts are returned for users with pending enrolment records.
*/
public function test_get_contexts_for_user(): void {
global $DB;
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
$this->assertEquals(5, $DB->count_records('enrol_flatfile'));
// We expect to see 2 entries for user1, in course1 and course3.
$contextlist = provider::get_contexts_for_userid($this->user1->id);
$this->assertEquals(2, $contextlist->count());
$contextids = $contextlist->get_contextids();
$this->assertContainsEquals($this->coursecontext1->id, $contextids);
$this->assertContainsEquals($this->coursecontext3->id, $contextids);
// And 1 for user2 on course2.
$contextlist = provider::get_contexts_for_userid($this->user2->id);
$this->assertEquals(1, $contextlist->count());
$contextids = $contextlist->get_contextids();
$this->assertContainsEquals($this->coursecontext2->id, $contextids);
}
/**
* Verify the export includes any future enrolment records for the user.
*/
public function test_export_user_data(): void {
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
// Get contexts containing user data.
$contextlist = provider::get_contexts_for_userid($this->user1->id);
$this->assertEquals(2, $contextlist->count());
$approvedcontextlist = new approved_contextlist(
$this->user1,
'enrol_flatfile',
$contextlist->get_contextids()
);
// Export for the approved contexts.
provider::export_user_data($approvedcontextlist);
// Verify we see one future course enrolment in course1, and one in course3.
$subcontext = \core_enrol\privacy\provider::get_subcontext([get_string('pluginname', 'enrol_flatfile')]);
$writer = writer::with_context($this->coursecontext1);
$this->assertNotEmpty($writer->get_data($subcontext));
$writer = writer::with_context($this->coursecontext3);
$this->assertNotEmpty($writer->get_data($subcontext));
// Verify we have nothing in course 2 for this user.
$writer = writer::with_context($this->coursecontext2);
$this->assertEmpty($writer->get_data($subcontext));
}
/**
* Verify export will limit any future enrolment records to only those contextids provided.
*/
public function test_export_user_data_restricted_context_subset(): void {
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
// Now, limit the export scope to just course1's context and verify only that data is seen in any export.
$subsetapprovedcontextlist = new approved_contextlist(
$this->user1,
'enrol_flatfile',
[$this->coursecontext1->id]
);
// Export for the approved contexts.
provider::export_user_data($subsetapprovedcontextlist);
// Verify we see one future course enrolment in course1 only.
$subcontext = \core_enrol\privacy\provider::get_subcontext([get_string('pluginname', 'enrol_flatfile')]);
$writer = writer::with_context($this->coursecontext1);
$this->assertNotEmpty($writer->get_data($subcontext));
// And nothing in the course3 context.
$writer = writer::with_context($this->coursecontext3);
$this->assertEmpty($writer->get_data($subcontext));
}
/**
* Verify that records can be deleted by context.
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
// Verify we have 3 future enrolments for course 1.
$this->assertEquals(3, $DB->count_records('enrol_flatfile', ['courseid' => $this->coursecontext1->instanceid]));
// Now, run delete by context and confirm that all records are removed.
provider::delete_data_for_all_users_in_context($this->coursecontext1);
$this->assertEquals(0, $DB->count_records('enrol_flatfile', ['courseid' => $this->coursecontext1->instanceid]));
}
public function test_delete_data_for_user(): void {
global $DB;
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
// Verify we have 2 future enrolments for course 1 and course 3.
$contextlist = provider::get_contexts_for_userid($this->user1->id);
$this->assertEquals(2, $contextlist->count());
$contextids = $contextlist->get_contextids();
$this->assertContainsEquals($this->coursecontext1->id, $contextids);
$this->assertContainsEquals($this->coursecontext3->id, $contextids);
$approvedcontextlist = new approved_contextlist(
$this->user1,
'enrol_flatfile',
$contextids
);
// Now, run delete for user and confirm that both records are removed.
provider::delete_data_for_user($approvedcontextlist);
$contextlist = provider::get_contexts_for_userid($this->user1->id);
$this->assertEquals(0, $contextlist->count());
$this->assertEquals(0, $DB->count_records('enrol_flatfile', ['userid' => $this->user1->id]));
}
/**
* Test for provider::get_users_in_context().
*/
public function test_get_users_in_context(): void {
global $DB;
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
$this->assertEquals(5, $DB->count_records('enrol_flatfile'));
// We expect to see 3 entries for course1, and that's user1, user3 and user4.
$userlist = new \core_privacy\local\request\userlist($this->coursecontext1, 'enrol_flatfile');
provider::get_users_in_context($userlist);
$this->assertEqualsCanonicalizing(
[$this->user1->id, $this->user3->id, $this->user4->id],
$userlist->get_userids());
// And 1 for course2 which is for user2.
$userlist = new \core_privacy\local\request\userlist($this->coursecontext2, 'enrol_flatfile');
provider::get_users_in_context($userlist);
$this->assertEquals([$this->user2->id], $userlist->get_userids());
// And 1 for course3 which is for user1 again.
$userlist = new \core_privacy\local\request\userlist($this->coursecontext3, 'enrol_flatfile');
provider::get_users_in_context($userlist);
$this->assertEquals([$this->user1->id], $userlist->get_userids());
}
/**
* Test for provider::delete_data_for_users().
*/
public function test_delete_data_for_users(): void {
global $DB;
// Create, via flatfile syncing, the future enrolments entries in the enrol_flatfile table.
$this->create_future_enrolments();
// Verify we have 3 future enrolment for user 1, user 3 and user 4.
$userlist = new \core_privacy\local\request\userlist($this->coursecontext1, 'enrol_flatfile');
provider::get_users_in_context($userlist);
$this->assertEqualsCanonicalizing(
[$this->user1->id, $this->user3->id, $this->user4->id],
$userlist->get_userids());
$approveduserlist = new \core_privacy\local\request\approved_userlist($this->coursecontext1, 'enrol_flatfile',
[$this->user1->id, $this->user3->id]);
// Now, run delete for user and confirm that the record is removed.
provider::delete_data_for_users($approveduserlist);
$userlist = new \core_privacy\local\request\userlist($this->coursecontext1, 'enrol_flatfile');
provider::get_users_in_context($userlist);
$this->assertEquals([$this->user4->id], $userlist->get_userids());
$this->assertEquals(
[$this->user4->id],
$DB->get_fieldset_select('enrol_flatfile', 'userid', 'courseid = ?', [$this->coursecontext1->instanceid])
);
}
/**
* Helper to sync a file and create the enrol_flatfile DB entries, for use with the get, export and delete tests.
*/
protected function create_future_enrolments() {
global $CFG;
$this->user1 = $this->getDataGenerator()->create_user(['idnumber' => 'u1']);
$this->user2 = $this->getDataGenerator()->create_user(['idnumber' => 'u2']);
$this->user3 = $this->getDataGenerator()->create_user(['idnumber' => 'u3']);
$this->user4 = $this->getDataGenerator()->create_user(['idnumber' => 'u4']);
$course1 = $this->getDataGenerator()->create_course(['idnumber' => 'c1']);
$course2 = $this->getDataGenerator()->create_course(['idnumber' => 'c2']);
$course3 = $this->getDataGenerator()->create_course(['idnumber' => 'c3']);
$this->coursecontext1 = \context_course::instance($course1->id);
$this->coursecontext2 = \context_course::instance($course2->id);
$this->coursecontext3 = \context_course::instance($course3->id);
$now = time();
$future = $now + 60 * 60 * 5;
$farfuture = $now + 60 * 60 * 24 * 5;
$file = "$CFG->dataroot/enrol.txt";
$data = "add,student,u1,c1,$future,0
add,student,u2,c2,$future,0
add,student,u3,c1,$future,0
add,student,u4,c1,$future,0
add,student,u1,c3,$future,$farfuture";
file_put_contents($file, $data);
$trace = new \null_progress_trace();
$this->enable_plugin();
$flatfileplugin = enrol_get_plugin('flatfile');
$flatfileplugin->set_config('location', $file);
$flatfileplugin->sync($trace);
}
/**
* Enables the flatfile plugin for testing.
*/
protected function enable_plugin() {
$enabled = enrol_get_plugins(true);
$enabled['flatfile'] = true;
$enabled = array_keys($enabled);
set_config('enrol_plugins_enabled', implode(',', $enabled));
}
}
+30
View File
@@ -0,0 +1,30 @@
<?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/>.
/**
* Flat file enrolment plugin version specification.
*
* @package enrol_flatfile
* @copyright 2010 Eugene Venter
* @author Eugene Venter
* @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: YYYYMMDDRR).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'enrol_flatfile'; // Full name of the plugin (used for diagnostics)