ÿØÿà 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-Ї Ç db/services.php000064400000003027152266450040007473 0ustar00. /** * Guest enrolment external functions and service definitions. * * @package enrol_guest * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ $functions = array( 'enrol_guest_get_instance_info' => array( 'classname' => 'enrol_guest_external', 'methodname' => 'get_instance_info', 'description' => 'Return guest enrolment instance information.', 'type' => 'read', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), ), 'enrol_guest_validate_password' => [ 'classname' => 'enrol_guest\external\validate_password', 'description' => 'Perform password validation.', 'type' => 'write', 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], ], ); db/access.php000064400000002262152266450040007111 0ustar00. /** * Capabilities for guest access plugin. * * @package enrol_guest * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $capabilities = array( 'enrol/guest:config' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) ), ); db/upgrade.php000064400000003023152266450040007273 0ustar00. /** * This file keeps track of upgrades to the guest enrolment plugin. * * @package enrol_guest * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function xmldb_enrol_guest_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; } lang/en/enrol_guest.php000064400000005245152266450040011140 0ustar00. /** * Strings for component 'enrol_guest', language 'en'. * * @package enrol_guest * @copyright 2010 onwards Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['allowguests'] = 'This course allows guest users to enter'; $string['guest:config'] = 'Configure guest access instances'; $string['guestaccess_withpassword'] = 'Guest access requires password'; $string['guestaccess_withoutpassword'] = 'Guest access'; $string['password'] = 'Password'; $string['password_help'] = 'A password allows guest access to the course to be restricted to only those who know the password. Guests will be required to supply the password each time they access the course.'; $string['passwordinvalid'] = 'Incorrect access password, please try again'; $string['passwordinvalidhint'] = 'That access password was incorrect, please try again
(Here\'s a hint - it starts with \'{$a}\')'; $string['passwordrequired'] = 'A password will be required.'; $string['pluginname'] = 'Guest access'; $string['pluginname_desc'] = 'Guest access plugin is only granting temporary access to courses, it is not actually enrolling users.'; $string['requirepassword'] = 'Require guest access password'; $string['requirepassword_desc'] = 'Require access password in new courses and prevent removing of access password from existing courses.'; $string['showhint'] = 'Show hint'; $string['showhint_desc'] = 'Show first letter of the guest access password.'; $string['status'] = 'Allow guest access'; $string['status_desc'] = 'Allow temporary guest access by default.'; $string['status_help'] = 'This setting determines whether a user can access the course as a guest, without being required to enrol.'; $string['status_link'] = 'enrol/guest'; $string['usepasswordpolicy'] = 'Use password policy'; $string['usepasswordpolicy_desc'] = 'Use standard password policy for guest access passwords.'; $string['privacy:metadata'] = 'The Guest access enrolment plugin does not store any personal data.'; pix/withoutpassword.svg000064400000000772152266450040011365 0ustar00 pix/withpassword.svg000064400000000741152266450040010631 0ustar00 lib.php000064400000050522152266450040006033 0ustar00. /** * Guest access plugin. * * This plugin does not add any entries into the user_enrolments table, * the access control is granted on the fly via the tricks in require_login(). * * @package enrol_guest * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ use core\output\single_button; use core_enrol\output\enrol_page; /** * Class enrol_guest_plugin * * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class enrol_guest_plugin extends enrol_plugin { /** * Returns optional enrolment information icons. * * This is used in course list for quick overview of enrolment options. * * We are not using single instance parameter because sometimes * we might want to prevent icon repetition when multiple instances * of one type exist. One instance may also produce several icons. * * @param array $instances all enrol instances of this type in one course * @return array of pix_icon */ public function get_info_icons(array $instances) { foreach ($instances as $instance) { if ($instance->password !== '') { return array(new pix_icon('withpassword', get_string('guestaccess_withpassword', 'enrol_guest'), 'enrol_guest')); } else { return array(new pix_icon('withoutpassword', get_string('guestaccess_withoutpassword', 'enrol_guest'), 'enrol_guest')); } } } /** * Enrol a user using a given enrolment instance. * * @param stdClass $instance * @param int $userid * @param null $roleid * @param int $timestart * @param int $timeend * @param null $status * @param null $recovergrades */ public function enrol_user(stdClass $instance, $userid, $roleid = null, $timestart = 0, $timeend = 0, $status = null, $recovergrades = null) { // no real enrolments here! return; } /** * Enrol a user from a given enrolment instance. * * @param stdClass $instance * @param int $userid */ public function unenrol_user(stdClass $instance, $userid) { // nothing to do, we never enrol here! return; } /** * Attempt to automatically gain temporary guest access to course, * calling code has to make sure the plugin and instance are active. * * @param stdClass $instance course enrol instance * @return bool|int false means no guest access, integer means end of cached time */ public function try_guestaccess(stdClass $instance) { global $USER, $CFG; $allow = false; if ($instance->password === '') { $allow = true; } else if (isset($USER->enrol_guest_passwords[$instance->id])) { // this is a hack, ideally we should not add stuff to $USER... if ($USER->enrol_guest_passwords[$instance->id] === $instance->password) { $allow = true; } } else if (WS_SERVER) { // Mobile app mostly. $storedpass = get_user_preferences('enrol_guest_ws_password_'. $instance->id); // We check first if there is a supplied password. if (!is_null($storedpass)) { $allow = $storedpass === $instance->password; if (!$allow) { // Reset, probably the course password was changed. unset_user_preference('enrol_guest_ws_password_' . $instance->id); } } } if ($allow) { // Temporarily assign them some guest role for this context $context = context_course::instance($instance->courseid); load_temp_course_role($context, $CFG->guestroleid); return ENROL_MAX_TIMESTAMP; } return false; } /** * Returns true if the current user can add a new instance of enrolment plugin in course. * @param int $courseid * @return boolean */ public function can_add_instance($courseid) { global $DB; $context = context_course::instance($courseid, MUST_EXIST); if (!has_capability('moodle/course:enrolconfig', $context) or !has_capability('enrol/guest:config', $context)) { return false; } if ($DB->record_exists('enrol', array('courseid'=>$courseid, 'enrol'=>'guest'))) { return false; } return true; } /** * Enrol a user using the guest enrolment method * * @param stdClass $instance * @param string $guestpassword * @return void */ public function mark_user_as_enrolled(stdClass $instance, string $guestpassword): void { global $USER, $CFG; // Add guest role. $context = \core\context\course::instance($instance->courseid); $USER->enrol_guest_passwords[$instance->id] = $guestpassword; if (isset($USER->enrol['tempguest'][$instance->courseid])) { remove_temp_course_roles($context); } load_temp_course_role($context, $CFG->guestroleid); $USER->enrol['tempguest'][$instance->courseid] = ENROL_MAX_TIMESTAMP; } #[\Override] public function enrol_page_hook(stdClass $instance) { global $CFG, $OUTPUT, $SESSION, $USER, $PAGE; if ($instance->password === '') { return null; } if (isset($USER->enrol['tempguest'][$instance->courseid]) and $USER->enrol['tempguest'][$instance->courseid] > time()) { // no need to show the guest access when user can already enter course as guest return null; } $title = $this->get_instance_name($instance); $notification = new \core\output\notification(get_string('passwordrequired', 'enrol_guest'), 'info', false); $notification->set_extra_classes(['mb-0']); $button = new single_button( $PAGE->url, get_string('loginguest', 'moodle'), 'get', single_button::BUTTON_PRIMARY, [ 'data-id' => $instance->courseid, 'data-instance' => $instance->id, 'data-form' => enrol_guest\form\enrol_form::class, 'data-title' => $title, ]); $PAGE->requires->js_call_amd('enrol_guest/enrol_page', 'initEnrol', [$instance->id]); $enrolpage = new enrol_page( instance: $instance, header: $title, body: $OUTPUT->render($notification), buttons: [$button]); return $OUTPUT->render($enrolpage); } /** * Called after updating/inserting course. * * @param bool $inserted true if course just inserted * @param object $course * @param object $data form data * @return void */ public function course_updated($inserted, $course, $data) { global $DB; if ($inserted) { if (isset($data->enrol_guest_status_0)) { $fields = array('status'=>$data->enrol_guest_status_0); if ($fields['status'] == ENROL_INSTANCE_ENABLED) { $fields['password'] = $data->enrol_guest_password_0; } else { if ($this->get_config('requirepassword')) { $fields['password'] = generate_password(20); } } $this->add_instance($course, $fields); } else { if ($this->get_config('defaultenrol')) { $this->add_default_instance($course); } } } else { $instances = $DB->get_records('enrol', array('courseid'=>$course->id, 'enrol'=>'guest')); foreach ($instances as $instance) { $i = $instance->id; if (isset($data->{'enrol_guest_status_'.$i})) { $reset = ($instance->status != $data->{'enrol_guest_status_'.$i}); $instance->status = $data->{'enrol_guest_status_'.$i}; $instance->timemodified = time(); if ($instance->status == ENROL_INSTANCE_ENABLED) { if ($instance->password !== $data->{'enrol_guest_password_'.$i}) { $reset = true; } $instance->password = $data->{'enrol_guest_password_'.$i}; } $DB->update_record('enrol', $instance); \core\event\enrol_instance_updated::create_from_record($instance)->trigger(); if ($reset) { $context = context_course::instance($course->id); $context->mark_dirty(); } } } } } /** * Add new instance of enrol plugin. * @param object $course * @param array instance fields * @return int id of new instance, null if can not be created */ public function add_instance($course, ?array $fields = NULL) { $fields = (array)$fields; if (!isset($fields['password'])) { $fields['password'] = ''; } return parent::add_instance($course, $fields); } /** * Add new instance of enrol plugin with default settings. * @param object $course * @return int id of new instance */ public function add_default_instance($course) { $fields = array('status'=>$this->get_config('status')); if ($this->get_config('requirepassword')) { $fields['password'] = generate_password(20); } return $this->add_instance($course, $fields); } /** * 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 (!$DB->record_exists('enrol', array('courseid' => $data->courseid, 'enrol' => $this->get_name()))) { $this->add_instance($course, (array)$data); } // No need to set mapping, we do not restore users or roles here. $step->set_mapping('enrol', $oldid, 0); } /** * 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/guest:config', $context); } /** * Is it possible to hide/show enrol instance via standard UI? * * @param stdClass $instance * @return bool */ public function can_hide_show_instance($instance) { $context = context_course::instance($instance->courseid); if (!has_capability('enrol/guest:config', $context)) { return false; } // If the instance is currently disabled, before it can be enabled, we must check whether the password meets the // password policies. if ($instance->status == ENROL_INSTANCE_DISABLED) { if ($this->get_config('requirepassword')) { if (empty($instance->password)) { return false; } } // Only check the password if it is set. if (!empty($instance->password) && $this->get_config('usepasswordpolicy')) { if (!check_password_policy($instance->password, $errmsg)) { return false; } } } return true; } /** * Get default settings for enrol_guest. * * @return array */ public function get_instance_defaults() { $fields = array(); $fields['status'] = $this->get_config('status'); return $fields; } /** * Return information for enrolment instance containing list of parameters required * for enrolment, name of enrolment plugin etc. * * @param stdClass $instance enrolment instance * @return stdClass instance info. * @since Moodle 3.1 */ public function get_enrol_info(stdClass $instance) { $instanceinfo = new stdClass(); $instanceinfo->id = $instance->id; $instanceinfo->courseid = $instance->courseid; $instanceinfo->type = $this->get_name(); $instanceinfo->name = $this->get_instance_name($instance); $instanceinfo->status = $instance->status == ENROL_INSTANCE_ENABLED; // Specifics enrolment method parameters. $instanceinfo->requiredparam = new stdClass(); $instanceinfo->requiredparam->passwordrequired = !empty($instance->password); // If the plugin is enabled, return the URL for obtaining more information. if ($instanceinfo->status) { $instanceinfo->wsfunction = 'enrol_guest_get_instance_info'; } return $instanceinfo; } /** * Return an array of valid options for the status. * * @return array */ protected function get_status_options() { $options = array(ENROL_INSTANCE_ENABLED => get_string('yes'), ENROL_INSTANCE_DISABLED => get_string('no')); return $options; } /** * Add elements to the edit instance form. * * @param stdClass $instance * @param MoodleQuickForm $mform * @param context $context * @return bool */ public function edit_instance_form($instance, MoodleQuickForm $mform, $context) { global $CFG; $options = $this->get_status_options(); $mform->addElement('select', 'status', get_string('status', 'enrol_guest'), $options); $mform->addHelpButton('status', 'status', 'enrol_guest'); $mform->setDefault('status', $this->get_config('status')); $mform->setAdvanced('status', $this->get_config('status_adv')); $mform->addElement('passwordunmask', 'password', get_string('password', 'enrol_guest')); $mform->addHelpButton('password', 'password', 'enrol_guest'); // If we have a new instance and the password is required - make sure it is set. For existing // instances we do not force the password to be required as it may have been set to empty before // the password was required. We check in the validation function whether this check is required // for existing instances. if (empty($instance->id) && $this->get_config('requirepassword')) { $mform->addRule('password', get_string('required'), 'required', null); } } /** * We are a good plugin and don't invent our own UI/validation code path. * * @return boolean */ public function use_standard_editing_ui() { return true; } /** * Perform custom validation of the data used to edit the instance. * * @param array $data array of ("fieldname"=>value) of submitted data * @param array $files array of uploaded files "element_name"=>tmp_file_path * @param object $instance The instance loaded from the DB * @param context $context The context of the instance we are editing * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK. * @return void */ public function edit_instance_validation($data, $files, $instance, $context) { $errors = array(); $checkpassword = false; if ($data['id']) { // Check the password if we are enabling the plugin again. if (($instance->status == ENROL_INSTANCE_DISABLED) && ($data['status'] == ENROL_INSTANCE_ENABLED)) { $checkpassword = true; } // Check the password if the instance is enabled and the password has changed. if (($data['status'] == ENROL_INSTANCE_ENABLED) && ($instance->password !== $data['password'])) { $checkpassword = true; } } else { $checkpassword = true; } if ($checkpassword) { $require = $this->get_config('requirepassword'); $policy = $this->get_config('usepasswordpolicy'); if ($require && trim($data['password']) === '') { $errors['password'] = get_string('required'); } else if (!empty($data['password']) && $policy) { $errmsg = ''; if (!check_password_policy($data['password'], $errmsg)) { $errors['password'] = $errmsg; } } } $validstatus = array_keys($this->get_status_options()); $tovalidate = array( 'status' => $validstatus ); $typeerrors = $this->validate_param_types($data, $tovalidate); $errors = array_merge($errors, $typeerrors); return $errors; } /** * Check if enrolment plugin is supported in csv course upload. * * @return bool */ public function is_csv_upload_supported(): bool { return true; } /** * Finds matching instances for a given course. * * @param array $enrolmentdata enrolment data. * @param int $courseid Course ID. * @return stdClass|null Matching instance */ public function find_instance(array $enrolmentdata, int $courseid): ?stdClass { $instances = enrol_get_instances($courseid, false); $instance = null; foreach ($instances as $i) { if ($i->enrol == 'guest') { // There can be only one guest enrol instance so find first available. $instance = $i; break; } } return $instance; } /** * Fill custom fields data for a given enrolment plugin. * * @param array $enrolmentdata enrolment data. * @param int $courseid Course ID. * @return array Updated enrolment data with custom fields info. */ public function fill_enrol_custom_fields(array $enrolmentdata, int $courseid): array { return $enrolmentdata + ['password' => '']; } /** * Updates enrol plugin instance with provided data. * @param int $courseid Course ID. * @param array $enrolmentdata enrolment data. * @param stdClass $instance Instance to update. * * @return stdClass updated instance */ public function update_enrol_plugin_data(int $courseid, array $enrolmentdata, stdClass $instance): stdClass { if (!empty($enrolmentdata['password'])) { $instance->password = $enrolmentdata['password']; } return parent::update_enrol_plugin_data($courseid, $enrolmentdata, $instance); } /** * Check if data is valid for a given enrolment plugin * * @param array $enrolmentdata enrolment data to validate. * @param int|null $courseid Course ID. * @return array Errors */ public function validate_enrol_plugin_data(array $enrolmentdata, ?int $courseid = null): array { // If password is omitted or empty in csv it will be generated automatically if it is a required policy. $errors = parent::validate_enrol_plugin_data($enrolmentdata, $courseid); $policy = $this->get_config('usepasswordpolicy'); if (!empty($enrolmentdata['password']) && $policy) { $errarray = get_password_policy_errors($enrolmentdata['password']); foreach ($errarray as $i => $err) { $errors['enrol_guest' . $i] = $err; } } return $errors; } } /** * Get icon mapping for font-awesome. */ function enrol_guest_get_fontawesome_icon_map() { return [ 'enrol_guest:withoutpassword' => 'fa-lock-open', 'enrol_guest:withpassword' => 'fa-lock', ]; } version.php000064400000002254152266450040006751 0ustar00. /** * Guest access plugin version specification. * * @package enrol_guest * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2025041400; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2025040800; // Requires this Moodle version. $plugin->component = 'enrol_guest'; // Full name of the plugin (used for diagnostics) classes/external.php000064400000010637152266450040010547 0ustar00. /** * Guest enrolment method external API * * @package enrol_guest * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ use core_external\external_api; use core_external\external_description; use core_external\external_function_parameters; use core_external\external_single_structure; use core_external\external_value; use core_external\external_warnings; defined('MOODLE_INTERNAL') || die; require_once($CFG->libdir . '/enrollib.php'); /** * Guest enrolment method external API * * @package enrol_guest * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ class enrol_guest_external extends external_api { /** * Returns description of get_instance_info() parameters. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_instance_info_parameters() { return new external_function_parameters( array('instanceid' => new external_value(PARAM_INT, 'Instance id of guest enrolment plugin.')) ); } /** * Return guest enrolment instance information. * * @param int $instanceid instance id of guest enrolment plugin. * @return array warnings and instance information. * @since Moodle 3.1 */ public static function get_instance_info($instanceid) { global $DB; $params = self::validate_parameters(self::get_instance_info_parameters(), array('instanceid' => $instanceid)); $warnings = array(); // Retrieve guest enrolment plugin. $enrolplugin = enrol_get_plugin('guest'); if (empty($enrolplugin)) { throw new moodle_exception('invaliddata', 'error'); } self::validate_context(context_system::instance()); $enrolinstance = $DB->get_record('enrol', array('id' => $params['instanceid']), '*', MUST_EXIST); $course = $DB->get_record('course', array('id' => $enrolinstance->courseid), '*', MUST_EXIST); if (!core_course_category::can_view_course_info($course) && !can_access_course($course)) { throw new moodle_exception('coursehidden'); } $instanceinfo = $enrolplugin->get_enrol_info($enrolinstance); // Specific instance information. $instanceinfo->passwordrequired = $instanceinfo->requiredparam->passwordrequired; unset($instanceinfo->requiredparam); $result = array(); $result['instanceinfo'] = $instanceinfo; $result['warnings'] = $warnings; return $result; } /** * Returns description of get_instance_info() result value. * * @return external_description * @since Moodle 3.1 */ public static function get_instance_info_returns() { return new external_single_structure( array( 'instanceinfo' => new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'Id of course enrolment instance'), 'courseid' => new external_value(PARAM_INT, 'Id of course'), 'type' => new external_value(PARAM_PLUGIN, 'Type of enrolment plugin'), 'name' => new external_value(PARAM_RAW, 'Name of enrolment plugin'), 'status' => new external_value(PARAM_BOOL, 'Is the enrolment enabled?'), 'passwordrequired' => new external_value(PARAM_BOOL, 'Is a password required?'), ) ), 'warnings' => new external_warnings() ) ); } } classes/form/enrol_form.php000064400000012502152266450040012023 0ustar00. declare(strict_types=1); namespace enrol_guest\form; use core\context\course as context_course; use core_form\dynamic_form; use core_text; use moodle_url; /** * Form for entering password for guest enrolment * * @package enrol_guest * @copyright Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class enrol_form extends dynamic_form { /** @var \stdClass */ protected $instance; /** * Returns the instance of the enrolment method * * @throws \moodle_exception * @return \stdClass */ protected function get_instance(): \stdClass { global $DB, $CFG; require_once($CFG->dirroot . '/lib/enrollib.php'); if ($this->instance === null) { $courseid = $this->optional_param('id', 0, PARAM_INT); $instanceid = $this->optional_param('instance', 0, PARAM_INT); // We need enrol_get_instances() to validate that the enrolment method is enabled. $instances = enrol_get_instances($courseid, true); if (empty($instances[$instanceid]) || $instances[$instanceid]->enrol !== 'guest') { throw new \moodle_exception('invalidenrolinstance', 'enrol'); } $this->instance = $instances[$instanceid] ?? null; } return $this->instance; } #[\Override] public function definition() { $mform = $this->_form; $mform->addElement('password', 'guestpassword', get_string('password', 'enrol_guest')); $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'instance'); $mform->setType('instance', PARAM_INT); } #[\Override] public function validation($data, $files) { global $DB, $CFG; $errors = parent::validation($data, $files); $instance = $this->get_instance(); if ($instance->password !== '') { if ($data['guestpassword'] !== $instance->password) { $plugin = enrol_get_plugin('guest'); if ($plugin->get_config('showhint')) { $hint = core_text::substr($instance->password, 0, 1); $errors['guestpassword'] = get_string('passwordinvalidhint', 'enrol_guest', $hint); } else { $errors['guestpassword'] = get_string('passwordinvalid', 'enrol_guest'); } } } return $errors; } #[\Override] protected function check_access_for_dynamic_submission(): void { global $USER, $CFG; $courseid = $this->get_instance()->courseid; $course = get_course($courseid); $context = context_course::instance($this->get_instance()->courseid); if (!\core_course_category::can_view_course_info($course) && !is_enrolled($context, $USER, '', true)) { throw new \moodle_exception('coursehidden', '', $CFG->wwwroot . '/'); } } #[\Override] protected function get_context_for_dynamic_submission(): \context { // This form is used for users who are not yet enrolled in the course and do not have access to the course. // For the purpose of permission checks they must be able to access the course category for this course. return context_course::instance($this->get_instance()->courseid)->get_parent_context(); } #[\Override] protected function get_page_url_for_dynamic_submission(): moodle_url { $instance = $this->get_instance(); return new moodle_url('/enrol/index.php', ['id' => $instance->courseid, 'instance' => $instance->id]); } /** * Process the form submission, used if form was submitted via AJAX * * Enrols the user in the course and returns the URL to redirect to * * @return string */ public function process_dynamic_submission() { global $USER, $CFG, $SESSION; /** @var \enrol_guest_plugin $enrol */ $enrol = enrol_get_plugin('guest'); $instance = $this->get_instance(); $enrol->mark_user_as_enrolled($instance, $this->get_data()->guestpassword); // Go to the originally requested page. if (!empty($SESSION->wantsurl)) { $destination = $SESSION->wantsurl; unset($SESSION->wantsurl); } else { require_once($CFG->dirroot . '/course/lib.php'); $destination = course_get_url($instance->courseid); } return $destination; } #[\Override] public function set_data_for_dynamic_submission(): void { $instance = $this->get_instance(); $this->set_data(['id' => $instance->courseid, 'instance' => $instance->id]); } } classes/external/validate_password.php000064400000011001152266450040014244 0ustar00. namespace enrol_guest\external; use core_external\external_api; use core_external\external_function_parameters; use core_external\external_single_structure; use core_external\external_value; use core_external\external_warnings; use context_system; use moodle_exception; use core_text; use stdClass; /** * This is the external method validating a guest password. * * @package enrol_guest * @since Moodle 4.3 * @copyright 2023 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class validate_password extends external_api { /** * Webservice parameters. * * @return external_function_parameters */ public static function execute_parameters(): external_function_parameters { return new external_function_parameters( [ 'instanceid' => new external_value(PARAM_INT, 'instance id of guest enrolment plugin'), 'password' => new external_value(PARAM_RAW, 'the course password'), ] ); } /** * Perform password validation. * * If password is correct: keep it as user preference. * If password is not correct: remove existing user preference (if any) * * @throws moodle_exception * @param int $instanceid instance id of guest enrolment plugin * @param string $password the course password * @return stdClass validation result info */ public static function execute(int $instanceid, string $password): stdClass { global $CFG, $DB; require_once($CFG->libdir . '/enrollib.php'); $params = external_api::validate_parameters(self::execute_parameters(), [ 'instanceid' => $instanceid, 'password' => $password, ]); $warnings = []; $validated = false; $hint = ''; // Retrieve guest enrolment plugin. $enrolplugin = enrol_get_plugin('guest'); if (empty($enrolplugin)) { throw new moodle_exception('invaliddata', 'error'); } self::validate_context(context_system::instance()); $enrolinstance = $DB->get_record('enrol', ['id' => $params['instanceid'], 'status' => ENROL_INSTANCE_ENABLED], '*', MUST_EXIST); $course = $DB->get_record('course', ['id' => $enrolinstance->courseid], '*', MUST_EXIST); if (!\core_course_category::can_view_course_info($course) && !can_access_course($course)) { throw new moodle_exception('coursehidden'); } if ($enrolinstance->password) { if ($params['password'] === $enrolinstance->password) { $validated = true; set_user_preference('enrol_guest_ws_password_' . $enrolinstance->id, $params['password']); } else { // Always unset in case there was something stored. unset_user_preference('enrol_guest_ws_password_' . $enrolinstance->id); if ($enrolplugin->get_config('showhint')) { $hint = core_text::substr($enrolinstance->password, 0, 1); $hint = get_string('passwordinvalidhint', 'enrol_guest', $hint); } } } $result = (object)[ 'validated' => $validated, 'hint' => $hint, 'warnings' => $warnings, ]; return $result; } /** * Describes the return information. * * @return external_single_structure */ public static function execute_returns(): external_single_structure { return new external_single_structure([ 'validated' => new external_value(PARAM_BOOL, 'Whether the password was successfully validated'), 'hint' => new external_value(PARAM_RAW, 'Password hint (if enabled)', VALUE_OPTIONAL), 'warnings' => new external_warnings(), ]); } } classes/privacy/provider.php000064400000002754152266450040012235 0ustar00. /** * Privacy Subsystem implementation for enrol_guest. * * @package enrol_guest * @copyright 2018 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace enrol_guest\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for enrol_guest 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\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason(): string { return 'privacy:metadata'; } }locallib.php000064400000006530152266450040007046 0ustar00. defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/formslib.php"); /** * Guest access plugin implementation. * * @deprecated since Moodle 5.0 - please use {@see enrol_guest\form\enrol_form} * * @package enrol_guest * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ #[\core\attribute\deprecated(replacement: enrol_guest\form\enrol_form::class, since: '5.0', reason: 'Now a dynamic form is used')] class enrol_guest_enrol_form extends moodleform { protected $instance; /** * Constructor * * @param mixed $action * @param mixed $customdata * @param string $method * @param string $target * @param mixed $attributes * @param bool $editable * @param array $ajaxformdata */ public function __construct($action=null, $customdata=null, $method='post', $target='', $attributes=null, $editable=true, $ajaxformdata=null) { \core\deprecation::emit_deprecation([$this, __FUNCTION__]); parent::__construct($action, $customdata, $method, $target, $attributes, $editable, $ajaxformdata); } public function definition() { $mform = $this->_form; $instance = $this->_customdata; $this->instance = $instance; $plugin = enrol_get_plugin('guest'); $heading = $plugin->get_instance_name($instance); $mform->addElement('header', 'guestheader', $heading); $mform->addElement('password', 'guestpassword', get_string('password', 'enrol_guest')); $this->add_action_buttons(false, get_string('submit')); $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $mform->setDefault('id', $instance->courseid); $mform->addElement('hidden', 'instance'); $mform->setType('instance', PARAM_INT); $mform->setDefault('instance', $instance->id); } public function validation($data, $files) { global $DB, $CFG; $errors = parent::validation($data, $files); $instance = $this->instance; if ($instance->password !== '') { if ($data['guestpassword'] !== $instance->password) { $plugin = enrol_get_plugin('guest'); if ($plugin->get_config('showhint')) { $hint = core_text::substr($instance->password, 0, 1); $errors['guestpassword'] = get_string('passwordinvalidhint', 'enrol_guest', $hint); } else { $errors['guestpassword'] = get_string('passwordinvalid', 'enrol_guest'); } } } return $errors; } } amd/src/enrol_page.js000064400000004432152266450040010554 0ustar00// 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 . /** * Functions for the enrol_guest plugin * * @module enrol_guest/enrol_page * @copyright Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import ModalForm from 'core_form/modalform'; import {getString} from 'core/str'; import {prefetchStrings} from 'core/prefetch'; import Url from 'core/url'; /** * Initialise widget on the course enrolment page - clicking on the button should submit the form * * @param {Number} instanceId */ export function initEnrol(instanceId) { prefetchStrings('moodle', [ 'loginguest', ]); const button = document.querySelector('button[type="submit"][data-instance="' + instanceId + '"]'); if (button) { button.addEventListener('click', (e) => { e.preventDefault(); const modalForm = new ModalForm({ modalConfig: { title: button.dataset.title, large: false, // This is a very small form that does not need a large popup. }, formClass: button.dataset.form, args: {id: button.dataset.id, instance: instanceId}, saveButtonText: getString('loginguest', 'moodle'), returnFocus: button, }); // Redirect to the course page when the form is submitted. modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => { window.location.href = event.detail ? event.detail : Url.relativeUrl('/course/view.php', {id: button.dataset.id}); }); modalForm.show(); }); } } amd/build/enrol_page.min.js000064400000002457152266450040011653 0ustar00define("enrol_guest/enrol_page",["exports","core_form/modalform","core/str","core/prefetch","core/url"],(function(_exports,_modalform,_str,_prefetch,_url){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} /** * Functions for the enrol_guest plugin * * @module enrol_guest/enrol_page * @copyright Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.initEnrol=function(instanceId){(0,_prefetch.prefetchStrings)("moodle",["loginguest"]);const button=document.querySelector('button[type="submit"][data-instance="'+instanceId+'"]');button&&button.addEventListener("click",(e=>{e.preventDefault();const modalForm=new _modalform.default({modalConfig:{title:button.dataset.title,large:!1},formClass:button.dataset.form,args:{id:button.dataset.id,instance:instanceId},saveButtonText:(0,_str.getString)("loginguest","moodle"),returnFocus:button});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(event=>{window.location.href=event.detail?event.detail:_url.default.relativeUrl("/course/view.php",{id:button.dataset.id})})),modalForm.show()}))},_modalform=_interopRequireDefault(_modalform),_url=_interopRequireDefault(_url)})); //# sourceMappingURL=enrol_page.min.js.mapamd/build/enrol_page.min.js.map000064400000006327152266450040012427 0ustar00{"version":3,"file":"enrol_page.min.js","sources":["../src/enrol_page.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Functions for the enrol_guest plugin\n *\n * @module enrol_guest/enrol_page\n * @copyright Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\nimport Url from 'core/url';\n\n/**\n * Initialise widget on the course enrolment page - clicking on the button should submit the form\n *\n * @param {Number} instanceId\n */\nexport function initEnrol(instanceId) {\n prefetchStrings('moodle', [\n 'loginguest',\n ]);\n\n const button = document.querySelector('button[type=\"submit\"][data-instance=\"' + instanceId + '\"]');\n if (button) {\n button.addEventListener('click', (e) => {\n e.preventDefault();\n const modalForm = new ModalForm({\n modalConfig: {\n title: button.dataset.title,\n large: false, // This is a very small form that does not need a large popup.\n },\n formClass: button.dataset.form,\n args: {id: button.dataset.id, instance: instanceId},\n saveButtonText: getString('loginguest', 'moodle'),\n returnFocus: button,\n });\n\n // Redirect to the course page when the form is submitted.\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n window.location.href = event.detail ? event.detail :\n Url.relativeUrl('/course/view.php', {id: button.dataset.id});\n });\n\n modalForm.show();\n });\n }\n}\n"],"names":["instanceId","button","document","querySelector","addEventListener","e","preventDefault","modalForm","ModalForm","modalConfig","title","dataset","large","formClass","form","args","id","instance","saveButtonText","returnFocus","events","FORM_SUBMITTED","event","window","location","href","detail","Url","relativeUrl","show"],"mappings":";;;;;;;yFAiC0BA,0CACN,SAAU,CACtB,qBAGEC,OAASC,SAASC,cAAc,wCAA0CH,WAAa,MACzFC,QACAA,OAAOG,iBAAiB,SAAUC,IAC9BA,EAAEC,uBACIC,UAAY,IAAIC,mBAAU,CAC5BC,YAAa,CACTC,MAAOT,OAAOU,QAAQD,MACtBE,OAAO,GAEXC,UAAWZ,OAAOU,QAAQG,KAC1BC,KAAM,CAACC,GAAIf,OAAOU,QAAQK,GAAIC,SAAUjB,YACxCkB,gBAAgB,kBAAU,aAAc,UACxCC,YAAalB,SAIjBM,UAAUH,iBAAiBG,UAAUa,OAAOC,gBAAgBC,QACxDC,OAAOC,SAASC,KAAOH,MAAMI,OAASJ,MAAMI,OACxCC,aAAIC,YAAY,mBAAoB,CAACZ,GAAIf,OAAOU,QAAQK,QAGhET,UAAUsB"}UPGRADING.md000064400000000340152266450040006407 0ustar00# enrol_guest Upgrade notes ## 5.0 ### Deprecated - Class enrol_guest_enrol_form is deprecated, use enrol_guest\form\enrol_form instead For more information see [MDL-84142](https://tracker.moodle.org/browse/MDL-84142) tests/external/validate_password_test.php000064400000006171152266450040015024 0ustar00. namespace enrol_guest\external; use core_external\external_api; /** * Tests for validate_password class. * * @package enrol_guest * @covers \enrol_guest\external\validate_password */ final class validate_password_test extends \advanced_testcase { public function test_execute(): void { global $DB; $this->resetAfterTest(); $course = self::getDataGenerator()->create_course(); $studentrole = $DB->get_record('role', ['shortname' => 'student']); $student = self::getDataGenerator()->create_user(); $pass = 'abc'; // Add enrolment methods for course. $guestplugin = enrol_get_plugin('guest'); $instanceid = $guestplugin->add_instance($course, [ 'status' => ENROL_INSTANCE_ENABLED, 'name' => 'Test instance', 'customint6' => 1, 'password' => $pass, 'roleid' => $studentrole->id, ]); $this->setUser($student); // Invalid password. $result = validate_password::execute($instanceid, 'z'); $result = external_api::clean_returnvalue(validate_password::execute_returns(), $result); $this->assertFalse($result['validated']); $this->assertEmpty($result['hint']); // Set invalid password preference. set_user_preference('enrol_guest_ws_password_' . $instanceid, 'y'); // Enable hint for invalid password. set_config('showhint', 1, 'enrol_guest'); $result = validate_password::execute($instanceid, 'z'); $result = external_api::clean_returnvalue(validate_password::execute_returns(), $result); $this->assertFalse($result['validated']); $this->assertNotEmpty($result['hint']); // Check hint. $this->assertNull(get_user_preferences('enrol_guest_ws_password_'. $instanceid)); // Check preference was reset. // Try valid password. $result = validate_password::execute($instanceid, $pass); $result = external_api::clean_returnvalue(validate_password::execute_returns(), $result); $this->assertTrue($result['validated']); // Check correct user preference. $this->assertEquals($pass, get_user_preferences('enrol_guest_ws_password_'. $instanceid)); // Course hidden, expect exception. $DB->set_field('course', 'visible', 0, ['id' => $course->id]); $this->expectException(\moodle_exception::class); $result = validate_password::execute($instanceid, ''); } } tests/external/external_test.php000064400000012054152266450040013130 0ustar00. /** * Self enrol external PHPunit tests * * @package enrol_guest * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ namespace enrol_guest\external; use core_external\external_api; use enrol_guest_external; use externallib_advanced_testcase; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/webservice/tests/helpers.php'); /** * Guest enrolment external functions tests * * @package enrol_guest * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ final class external_test extends externallib_advanced_testcase { /** * Test get_instance_info */ public function test_get_instance_info(): void { global $DB; $this->resetAfterTest(true); // Check if guest enrolment plugin is enabled. $guestplugin = enrol_get_plugin('guest'); $this->assertNotEmpty($guestplugin); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $coursedata = new \stdClass(); $coursedata->visible = 0; $course = self::getDataGenerator()->create_course($coursedata); $student = self::getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual'); // Add enrolment methods for course. $instance = $guestplugin->add_instance($course, array('status' => ENROL_INSTANCE_ENABLED, 'name' => 'Test instance', 'customint6' => 1, 'roleid' => $studentrole->id)); $this->setAdminUser(); $result = enrol_guest_external::get_instance_info($instance); $result = external_api::clean_returnvalue(enrol_guest_external::get_instance_info_returns(), $result); $this->assertEquals($instance, $result['instanceinfo']['id']); $this->assertEquals($course->id, $result['instanceinfo']['courseid']); $this->assertEquals('guest', $result['instanceinfo']['type']); $this->assertEquals('Test instance', $result['instanceinfo']['name']); $this->assertTrue($result['instanceinfo']['status']); $this->assertFalse($result['instanceinfo']['passwordrequired']); $DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id' => $instance)); $result = enrol_guest_external::get_instance_info($instance); $result = external_api::clean_returnvalue(enrol_guest_external::get_instance_info_returns(), $result); $this->assertEquals($instance, $result['instanceinfo']['id']); $this->assertEquals($course->id, $result['instanceinfo']['courseid']); $this->assertEquals('guest', $result['instanceinfo']['type']); $this->assertEquals('Test instance', $result['instanceinfo']['name']); $this->assertFalse($result['instanceinfo']['status']); $this->assertFalse($result['instanceinfo']['passwordrequired']); $DB->set_field('enrol', 'status', ENROL_INSTANCE_ENABLED, array('id' => $instance)); // Try to retrieve information using a normal user for a hidden course. $user = self::getDataGenerator()->create_user(); $this->setUser($user); try { enrol_guest_external::get_instance_info($instance); } catch (\moodle_exception $e) { $this->assertEquals('coursehidden', $e->errorcode); } // Student user. $DB->set_field('course', 'visible', 1, array('id' => $course->id)); $this->setUser($student); $result = enrol_guest_external::get_instance_info($instance); $result = external_api::clean_returnvalue(enrol_guest_external::get_instance_info_returns(), $result); $this->assertEquals($instance, $result['instanceinfo']['id']); $this->assertEquals($course->id, $result['instanceinfo']['courseid']); $this->assertEquals('guest', $result['instanceinfo']['type']); $this->assertEquals('Test instance', $result['instanceinfo']['name']); $this->assertTrue($result['instanceinfo']['status']); $this->assertFalse($result['instanceinfo']['passwordrequired']); } } tests/lib_test.php000064400000012167152266450040010237 0ustar00. /** * Guest enrolment tests. * * @package enrol_guest * @category phpunit * @copyright 2023 Ilya Tregubov * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace enrol_guest; final class lib_test extends \advanced_testcase { /** * Test the behaviour of validate_enrol_plugin_data(). * * @covers ::validate_enrol_plugin_data */ public function test_validate_enrol_plugin_data(): void { global $CFG; $this->resetAfterTest(); $guestplugin = enrol_get_plugin('guest'); $guestplugin->set_config('usepasswordpolicy', false); $enrolmentdata = []; $errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata); $this->assertEmpty($errors); // Now enable some controls, and check that the policy responds with policy text. $guestplugin->set_config('usepasswordpolicy', true); $CFG->minpasswordlength = 8; $CFG->minpassworddigits = 1; $CFG->minpasswordlower = 1; $CFG->minpasswordupper = 1; $CFG->minpasswordnonalphanum = 1; $CFG->maxconsecutiveidentchars = 1; $errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata); // If password is omitted it will be autocreated so nothing to validate. $this->assertEmpty($errors); $enrolmentdata = ['password' => 'test']; $errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata); $this->assertCount(4, $errors); $this->assertEquals(get_string('errorminpasswordlength', 'auth', $CFG->minpasswordlength), $errors['enrol_guest0']); $this->assertEquals(get_string('errorminpassworddigits', 'auth', $CFG->minpassworddigits), $errors['enrol_guest1']); $this->assertEquals(get_string('errorminpasswordupper', 'auth', $CFG->minpasswordupper), $errors['enrol_guest2']); $this->assertEquals(get_string('errorminpasswordnonalphanum', 'auth', $CFG->minpasswordnonalphanum), $errors['enrol_guest3']); $enrolmentdata = ['password' => 'Testingtest123@']; $errors = $guestplugin->validate_enrol_plugin_data($enrolmentdata); $this->assertEmpty($errors); } /** * Test the behaviour of update_enrol_plugin_data(). * * @covers ::update_enrol_plugin_data */ public function test_update_enrol_plugin_data(): void { global $DB; $this->resetAfterTest(); $manualplugin = enrol_get_plugin('guest'); $admin = get_admin(); $this->setUser($admin); $enrolmentdata = []; $cat = $this->getDataGenerator()->create_category(); $course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']); $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'guest'], '*', MUST_EXIST); $expectedinstance = $instance; $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance); $this->assertEquals($expectedinstance, $modifiedinstance); $enrolmentdata['password'] = 'test'; $expectedinstance->password = 'test'; $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance); $this->assertEquals($expectedinstance, $modifiedinstance); } /** * Test the behaviour of find_instance(). * * @covers ::find_instance */ public function test_find_instance(): void { global $DB; $this->resetAfterTest(); $cat = $this->getDataGenerator()->create_category(); // When we create a course, a guest enrolment instance is also created. $course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']); $guestplugin = enrol_get_plugin('guest'); $expected = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'guest']); // Let's try to add second instance - only 1 guest instance is possible. $instanceid2 = null; // Have to do this check since add_instance doesn't block adding second instance for guest plugin. if ($guestplugin->can_add_instance($course->id)) { $instanceid2 = $guestplugin->add_instance($course, []); } $this->assertNull($instanceid2); $enrolmentdata = []; $actual = $guestplugin->find_instance($enrolmentdata, $course->id); $this->assertEquals($expected->id, $actual->id); } } tests/behat/guest_access.feature000064400000003744152266450040013032 0ustar00@enrol @enrol_guest Feature: Guest users can auto-enrol themself in courses where guest access is allowed In order to access courses contents As a guest I need to access courses as a guest Background: Given the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@example.com | | student1 | Student | 1 | student1@example.com | And the following "courses" exist: | fullname | shortname | format | | Course 1 | C1 | topics | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | And the following "activity" exists: | activity | forum | | course | C1 | | idnumber | 0001 | | name | Test forum name | And I am on the "Course 1" "enrolment methods" page logged in as teacher1 Scenario: Allow guest access without password Given I click on "Edit" "link" in the "Guest access" "table_row" And I set the following fields to these values: | Allow guest access | Yes | And I press "Save changes" When I am on the "Test forum name" "forum activity" page logged in as student1 Then I should not see "Subscribe to this forum" @javascript Scenario: Allow guest access with password Given I click on "Edit" "link" in the "Guest access" "table_row" And I set the following fields to these values: | Allow guest access | Yes | | Password | moodle_rules | And I press "Save changes" When I am on the "Course 1" course page logged in as student1 Then I should see "Guest access" And I press "Access as a guest" And I set the following fields to these values: | Password | moodle_rules | And I click on "Access as a guest" "button" in the "Guest access" "dialogue" And I should see "Test forum name" settings.php000064400000005066152266450040007130 0ustar00. /** * Guest access plugin settings and presets. * * @package enrol_guest * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); if ($ADMIN->fulltree) { //--- general settings ----------------------------------------------------------------------------------- $settings->add(new admin_setting_heading('enrol_guest_settings', '', get_string('pluginname_desc', 'enrol_guest'))); $settings->add(new admin_setting_configcheckbox('enrol_guest/requirepassword', get_string('requirepassword', 'enrol_guest'), get_string('requirepassword_desc', 'enrol_guest'), 0)); $settings->add(new admin_setting_configcheckbox('enrol_guest/usepasswordpolicy', get_string('usepasswordpolicy', 'enrol_guest'), get_string('usepasswordpolicy_desc', 'enrol_guest'), 0)); $settings->add(new admin_setting_configcheckbox('enrol_guest/showhint', get_string('showhint', 'enrol_guest'), get_string('showhint_desc', 'enrol_guest'), 0)); //--- enrol instance defaults ---------------------------------------------------------------------------- $settings->add(new admin_setting_heading('enrol_guest_defaults', get_string('enrolinstancedefaults', 'admin'), get_string('enrolinstancedefaults_desc', 'admin'))); $settings->add(new admin_setting_configcheckbox('enrol_guest/defaultenrol', get_string('defaultenrol', 'enrol'), get_string('defaultenrol_desc', 'enrol'), 1)); $options = array(ENROL_INSTANCE_ENABLED => get_string('yes'), ENROL_INSTANCE_DISABLED => get_string('no')); $settings->add(new admin_setting_configselect_with_advanced('enrol_guest/status', get_string('status', 'enrol_guest'), get_string('status_desc', 'enrol_guest'), array('value'=>ENROL_INSTANCE_DISABLED, 'adv'=>false), $options)); }