ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç PK \ example.txtnu[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 PK \͵db/install.phpnu[. /** * 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'); } } PK \f  db/tasks.phpnu[. /** * 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' => '*' ) ); PK \ db/access.phpnu[. /** * 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( ) ), ); PK \/m  db/upgrade.phpnu[. /** * Keeps track of upgrades to the enrol_flatfile plugin * * @package enrol_flatfile * @copyright 2010 Aparup Banerjee * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function xmldb_enrol_flatfile_upgrade($oldversion) { // 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. // Automatically generated Moodle v4.5.0 release upgrade line. // Put any upgrade step following this. // Automatically generated Moodle v5.0.0 release upgrade line. // Put any upgrade step following this. return true; } PK \ZW  db/install.xmlnu[
PK \ndb/messages.phpnu[. /** * 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, ], ], ); PK \ tlang/en/enrol_flatfile.phpnu[. /** * 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:
   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
'; $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'; PK \k ;sslib.phpnu[. /** * 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&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); } } PK \ version.phpnu[. /** * 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 = 2025041400; // The current plugin version (Date: YYYYMMDDRR). $plugin->requires = 2025040800; // Requires this Moodle version. $plugin->component = 'enrol_flatfile'; // Full name of the plugin (used for diagnostics) PK \$ z@%@%classes/privacy/provider.phpnu[. /** * Privacy Subsystem implementation for enrol_flatfile. * * @package enrol_flatfile * @category privacy * @copyright 2018 Carlos Escobedo * @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 * @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; }, []); } } PK \Iȹ=LL#classes/task/flatfile_sync_task.phpnu[. /** * 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; } } PK \//)33 adminlib.phpnu[. /** * 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); } } PK \%Q0 cli/sync.phpnu[. /** * 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); PK \k =22tests/privacy/provider_test.phpnu[. /** * Privacy tests for enrol_flatfile. * * @package enrol_flatfile * @category test * @copyright 2018 Jake Dallimore * @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 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final 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 { parent::setUp(); $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)); } } PK \CJMjMjtests/flatfile_test.phpnu[. /** * 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 */ final 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); } } PK \, settings.phpnu[. /** * 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); } } PK \ example.txtnu[PK \͵db/install.phpnu[PK \f  db/tasks.phpnu[PK \  db/access.phpnu[PK \/m  db/upgrade.phpnu[PK \ZW  db/install.xmlnu[PK \nJdb/messages.phpnu[PK \ t8"lang/en/enrol_flatfile.phpnu[PK \k ;ssk2lib.phpnu[PK \ version.phpnu[PK \$ z@%@%classes/privacy/provider.phpnu[PK \Iȹ=LL#+classes/task/flatfile_sync_task.phpnu[PK \//)33 adminlib.phpnu[PK \%Q0 9cli/sync.phpnu[PK \k =22Itests/privacy/provider_test.phpnu[PK \CJMjMjqtests/flatfile_test.phpnu[PK \, settings.phpnu[PKb