ÿØÿà 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\B|ï styles.cssnu[.block_online_users .content .list li.listentry { clear: both; } .block_online_users .content .list li.listentry:not(:first-child) { padding-top: 3px; } .block_online_users .content .list li.listentry .user { float: left; position: relative; } .block_online_users .content .list li.listentry .otherusers { margin-left: 1.5rem; } .block_online_users .content .list li.listentry .user .userpicture { vertical-align: text-bottom; } .block_online_users .content .list li.listentry .message, .block_online_users .content .list li.listentry .uservisibility { float: right; margin-top: 3px; } .block_online_users .content .info { text-align: center; } PK\G:&G db/access.phpnu[. /** * Online users block caps. * * @package block_online_users * @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(); $capabilities = array( 'block/online_users:myaddinstance' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, 'archetypes' => array( 'user' => CAP_ALLOW ), 'clonepermissionsfrom' => 'moodle/my:manageblocks' ), 'block/online_users:addinstance' => array( 'riskbitmask' => RISK_SPAM | RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_BLOCK, 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ), 'clonepermissionsfrom' => 'moodle/site:manageblocks' ), 'block/online_users:viewlist' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_BLOCK, 'archetypes' => array( 'user' => CAP_ALLOW, 'guest' => CAP_PREVENT, 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ) ) ); PK\ W~,,lang/en/block_online_users.phpnu[. /** * Strings for component 'block_online_users', language 'en', branch 'MOODLE_20_STABLE' * * @package block_online_users * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['otherusers'] = 'Other users ({$a})'; $string['onlinestatushiding_desc'] = 'If enabled, users have the option to hide their online status from other users.'; $string['configtimetosee'] = 'Number of minutes determining the period of inactivity after which a user is no longer considered to be online.'; $string['onlinestatushiding'] = 'Online status hiding'; $string['nouser'] = 'No online users'; $string['numuser'] = '{$a} online user'; $string['numusers'] = '{$a} online users'; $string['online_users:addinstance'] = 'Add a new online users block'; $string['online_users:myaddinstance'] = 'Add a new online users block to Dashboard'; $string['online_users:viewlist'] = 'View list of online users'; $string['online_status:hide'] = 'Hide my online status from other users'; $string['online_status:show'] = 'Show my online status to other users'; $string['periodnminutes'] = 'last {$a} minutes'; $string['pluginname'] = 'Online users'; $string['timetosee'] = 'Remove after inactivity (minutes)'; $string['privacy:metadata:preference:uservisibility'] = 'Online status visible to other users in the Online users block.'; PK\i lib.phpnu[. /** * Contains functions called by core. * * @package block_online_users * @copyright 2018 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Callback to define user preferences. * * @return array */ function block_online_users_user_preferences() { $preferences = array(); $preferences['block_online_users_uservisibility'] = array( 'type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => 1, 'choices' => array(0, 1), 'permissioncallback' => function($user, $preferencename) { global $USER; return $user->id == $USER->id; } ); return $preferences; } PK\1 _ version.phpnu[. /** * Version details * * @package block_online_users * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @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 = 'block_online_users'; // Full name of the plugin (used for diagnostics) PK\i classes/privacy/provider.phpnu[. /** * Privacy Subsystem implementation for block_online_users. * * @package block_online_users * @copyright 2018 Zig Tan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace block_online_users\privacy; use core_privacy\local\metadata\collection; use core_privacy\local\request\writer; use core_privacy\local\request\transform; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for block_online_users. * * @copyright 2018 Zig Tan * @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\user_preference_provider { /** * Describe all the places where this plugin stores personal data. * * @param collection $collection Collection of items to add metadata to. * @return collection Collection with our added items. */ public static function get_metadata(collection $collection): collection { $collection->add_user_preference('block_online_users_uservisibility', 'privacy:metadata:preference:uservisibility'); return $collection; } /** * Export user preferences controlled by this plugin. * * @param int $userid ID of the user we are exporting data form. */ public static function export_user_preferences(int $userid) { $uservisibility = get_user_preferences('block_online_users_uservisibility', 1, $userid); writer::export_user_preference('block_online_users', 'block_online_users_uservisibility', transform::yesno($uservisibility), get_string('privacy:metadata:preference:uservisibility', 'block_online_users')); } } PK\<0classes/fetcher.phpnu[. /** * File containing onlineusers class. * * @package block_online_users * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace block_online_users; defined('MOODLE_INTERNAL') || die(); /** * Class used to list and count online users * * @package block_online_users * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class fetcher { /** @var string The SQL query for retrieving a list of online users */ public $sql; /** @var string The SQL query for counting the number of online users */ public $csql; /** @var string The params for the SQL queries */ public $params; /** * Class constructor * * @param int $currentgroup The group (if any) to filter on * @param int $now Time now * @param int $timetoshowusers Number of seconds to show online users * @param context $context Context object used to generate the sql for users enrolled in a specific course * @param bool $sitelevel Whether to check online users at site level. * @param int $courseid The course id to check */ public function __construct($currentgroup, $now, $timetoshowusers, $context, $sitelevel = true, $courseid = null) { $this->set_sql($currentgroup, $now, $timetoshowusers, $context, $sitelevel, $courseid); } /** * Store the SQL queries & params for listing online users * * @param int $currentgroup The group (if any) to filter on * @param int $now Time now * @param int $timetoshowusers Number of seconds to show online users * @param context $context Context object used to generate the sql for users enrolled in a specific course * @param bool $sitelevel Whether to check online users at site level. * @param int $courseid The course id to check */ protected function set_sql($currentgroup, $now, $timetoshowusers, $context, $sitelevel, $courseid) { global $USER, $DB, $CFG; $timefrom = 100 * floor(($now - $timetoshowusers) / 100); // Round to nearest 100 seconds for better query cache. $groupmembers = ""; $groupselect = ""; $groupby = ""; $lastaccess = ", lastaccess"; $timeaccess = ", ul.timeaccess AS lastaccess"; $uservisibility = ""; $uservisibilityselect = ""; if ($CFG->block_online_users_onlinestatushiding) { $uservisibility = ", up.value AS uservisibility"; $uservisibilityselect = "AND (" . $DB->sql_cast_char2int('up.value', true) . " = 1 OR up.value IS NULL OR u.id = :userid)"; } $params = array(); $userfieldsapi = \core_user\fields::for_userpic()->including('username', 'deleted'); $userfields = $userfieldsapi->get_sql('u', false, '', '', false)->selects; // Add this to the SQL to show only group users. if ($currentgroup !== null) { $groupmembers = ", {groups_members} gm"; $groupselect = "AND u.id = gm.userid AND gm.groupid = :currentgroup"; $groupby = "GROUP BY $userfields"; $lastaccess = ", MAX(u.lastaccess) AS lastaccess"; $timeaccess = ", MAX(ul.timeaccess) AS lastaccess"; if ($CFG->block_online_users_onlinestatushiding) { $uservisibility = ", MAX(" . $DB->sql_cast_char2int('up.value', true) . ") AS uservisibility"; } $params['currentgroup'] = $currentgroup; } $params['now'] = $now; $params['timefrom'] = $timefrom; $params['userid'] = $USER->id; $params['name'] = 'block_online_users_uservisibility'; if ($sitelevel) { $sql = "SELECT $userfields $lastaccess $uservisibility FROM {user} u $groupmembers LEFT JOIN {user_preferences} up ON up.userid = u.id AND up.name = :name WHERE u.lastaccess > :timefrom AND u.lastaccess <= :now AND u.deleted = 0 $uservisibilityselect $groupselect $groupby ORDER BY lastaccess DESC "; $csql = "SELECT COUNT(u.id) FROM {user} u $groupmembers LEFT JOIN {user_preferences} up ON up.userid = u.id AND up.name = :name WHERE u.lastaccess > :timefrom AND u.lastaccess <= :now AND u.deleted = 0 $uservisibilityselect $groupselect"; } else { // Course level - show only enrolled users for now. // TODO: add a new capability for viewing of all users (guests+enrolled+viewing). list($esqljoin, $eparams) = get_enrolled_sql($context); $params = array_merge($params, $eparams); $sql = "SELECT $userfields $timeaccess $uservisibility FROM {user_lastaccess} ul $groupmembers, {user} u JOIN ($esqljoin) euj ON euj.id = u.id LEFT JOIN {user_preferences} up ON up.userid = u.id AND up.name = :name WHERE ul.timeaccess > :timefrom AND u.id = ul.userid AND ul.courseid = :courseid AND ul.timeaccess <= :now AND u.deleted = 0 $uservisibilityselect $groupselect $groupby ORDER BY lastaccess DESC"; $csql = "SELECT COUNT(u.id) FROM {user_lastaccess} ul $groupmembers, {user} u JOIN ($esqljoin) euj ON euj.id = u.id LEFT JOIN {user_preferences} up ON up.userid = u.id AND up.name = :name WHERE ul.timeaccess > :timefrom AND u.id = ul.userid AND ul.courseid = :courseid AND ul.timeaccess <= :now AND u.deleted = 0 $uservisibilityselect $groupselect"; $params['courseid'] = $courseid; } $this->sql = $sql; $this->csql = $csql; $this->params = $params; } /** * Get a list of the most recent online users * * @param int $userlimit The maximum number of users that will be returned (optional, unlimited if not set) * @return array */ public function get_users($userlimit = 0) { global $DB; $users = $DB->get_records_sql($this->sql, $this->params, 0, $userlimit); return $users; } /** * Count the number of online users * * @return int */ public function count_users() { global $DB; return $DB->count_records_sql($this->csql, $this->params); } } PK\SCC!amd/src/change_user_visibility.jsnu[// 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 . /** * A javascript module that handles the change of the user's visibility in the * online users block. * * @module block_online_users/change_user_visibility * @copyright 2018 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import {getString} from 'core/str'; import Notification from 'core/notification'; import {setUserPreference} from 'core_user/repository'; /** * Selectors. * * @access private * @type {Object} */ const SELECTORS = { CHANGE_VISIBILITY_LINK: '#change-user-visibility', CHANGE_VISIBILITY_ICON: '#change-user-visibility .icon', }; /** * Change user visibility in the online users block. * * @method changeVisibility * @param {String} action * @param {String} userid * @returns {Promise} * @private */ const changeVisibility = (action, userid) => setUserPreference( 'block_online_users_uservisibility', action == "show" ? 1 : 0, userid, ) .then((data) => { if (data.saved) { const newAction = oppositeAction(action); changeVisibilityLinkAttr(newAction); changeVisibilityIconAttr(newAction); } return data; }).catch(Notification.exception); /** * Get the opposite action. * * @method oppositeAction * @param {String} action * @return {String} * @private */ const oppositeAction = (action) => action == 'show' ? 'hide' : 'show'; /** * Change the attribute values of the user visibility link in the online users block. * * @method changeVisibilityLinkAttr * @param {String} action * @returns {Promise} * @private */ const changeVisibilityLinkAttr = (action) => getTitle(action) .then((title) => { const link = document.querySelector(SELECTORS.CHANGE_VISIBILITY_LINK); link.dataset.action = action; link.title = title; return link; }); /** * Change the attribute values of the user visibility icon in the online users block. * * @method changeVisibilityIconAttr * @param {String} action * @returns {Promise} * @private */ const changeVisibilityIconAttr = (action) => getTitle(action) .then((title) => { const icon = document.querySelector(SELECTORS.CHANGE_VISIBILITY_ICON); // Add the proper title to the icon. icon.setAttribute('title', title); icon.setAttribute('aria-label', title); if (icon.closest("img")) { // If the icon is an image. icon.setAttribute('src', M.util.image_url(`t/${action}`)); icon.setAttribute('alt', title); } else { // Add the new icon class and remove the old one. icon.classList.add(getIconClass(action)); icon.classList.remove(getIconClass(oppositeAction(action))); } return title; }); /** * Get the proper class for the user visibility icon in the online users block. * * @method getIconClass * @param {String} action * @return {String} * @private */ const getIconClass = (action) => (action == 'show') ? 'fa-eye-slash' : 'fa-eye'; /** * Get the title description of the user visibility link in the online users block. * * @method getTitle * @param {String} action * @return {object} jQuery promise * @private */ const getTitle = (action) => getString(`online_status:${action}`, 'block_online_users'); /** * Initialise change user visibility function. * * @method init */ export const init = () => { document.addEventListener('click', (e) => { const link = e.target.closest(SELECTORS.CHANGE_VISIBILITY_LINK); if (!link) { return; } e.preventDefault(); changeVisibility( link.dataset.action, link.dataset.userid, ); }); }; PK\6z^DD+amd/build/change_user_visibility.min.js.mapnu[{"version":3,"file":"change_user_visibility.min.js","sources":["../src/change_user_visibility.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 * A javascript module that handles the change of the user's visibility in the\n * online users block.\n *\n * @module block_online_users/change_user_visibility\n * @copyright 2018 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getString} from 'core/str';\nimport Notification from 'core/notification';\nimport {setUserPreference} from 'core_user/repository';\n\n/**\n * Selectors.\n *\n * @access private\n * @type {Object}\n */\nconst SELECTORS = {\n CHANGE_VISIBILITY_LINK: '#change-user-visibility',\n CHANGE_VISIBILITY_ICON: '#change-user-visibility .icon',\n};\n\n/**\n * Change user visibility in the online users block.\n *\n * @method changeVisibility\n * @param {String} action\n * @param {String} userid\n * @returns {Promise}\n * @private\n */\nconst changeVisibility = (action, userid) => setUserPreference(\n 'block_online_users_uservisibility',\n action == \"show\" ? 1 : 0,\n userid,\n)\n.then((data) => {\n if (data.saved) {\n const newAction = oppositeAction(action);\n changeVisibilityLinkAttr(newAction);\n changeVisibilityIconAttr(newAction);\n }\n return data;\n}).catch(Notification.exception);\n\n/**\n * Get the opposite action.\n *\n * @method oppositeAction\n * @param {String} action\n * @return {String}\n * @private\n */\nconst oppositeAction = (action) => action == 'show' ? 'hide' : 'show';\n\n/**\n * Change the attribute values of the user visibility link in the online users block.\n *\n * @method changeVisibilityLinkAttr\n * @param {String} action\n * @returns {Promise}\n * @private\n */\nconst changeVisibilityLinkAttr = (action) => getTitle(action)\n .then((title) => {\n const link = document.querySelector(SELECTORS.CHANGE_VISIBILITY_LINK);\n link.dataset.action = action;\n link.title = title;\n return link;\n });\n\n/**\n * Change the attribute values of the user visibility icon in the online users block.\n *\n * @method changeVisibilityIconAttr\n * @param {String} action\n * @returns {Promise}\n * @private\n */\nconst changeVisibilityIconAttr = (action) => getTitle(action)\n .then((title) => {\n const icon = document.querySelector(SELECTORS.CHANGE_VISIBILITY_ICON);\n\n // Add the proper title to the icon.\n icon.setAttribute('title', title);\n icon.setAttribute('aria-label', title);\n\n if (icon.closest(\"img\")) {\n // If the icon is an image.\n icon.setAttribute('src', M.util.image_url(`t/${action}`));\n icon.setAttribute('alt', title);\n } else {\n // Add the new icon class and remove the old one.\n icon.classList.add(getIconClass(action));\n icon.classList.remove(getIconClass(oppositeAction(action)));\n }\n return title;\n });\n\n/**\n * Get the proper class for the user visibility icon in the online users block.\n *\n * @method getIconClass\n * @param {String} action\n * @return {String}\n * @private\n */\nconst getIconClass = (action) => (action == 'show') ? 'fa-eye-slash' : 'fa-eye';\n\n/**\n * Get the title description of the user visibility link in the online users block.\n *\n * @method getTitle\n * @param {String} action\n * @return {object} jQuery promise\n * @private\n */\nconst getTitle = (action) => getString(`online_status:${action}`, 'block_online_users');\n\n/**\n * Initialise change user visibility function.\n *\n * @method init\n */\nexport const init = () => {\n document.addEventListener('click', (e) => {\n const link = e.target.closest(SELECTORS.CHANGE_VISIBILITY_LINK);\n if (!link) {\n return;\n }\n e.preventDefault();\n changeVisibility(\n link.dataset.action,\n link.dataset.userid,\n );\n });\n};\n"],"names":["SELECTORS","oppositeAction","action","changeVisibilityLinkAttr","getTitle","then","title","link","document","querySelector","dataset","changeVisibilityIconAttr","icon","setAttribute","closest","M","util","image_url","classList","add","getIconClass","remove","addEventListener","e","target","userid","preventDefault","data","saved","newAction","catch","Notification","exception"],"mappings":";;;;;;;;4JAkCMA,iCACsB,0BADtBA,iCAEsB,gCAkCtBC,eAAkBC,QAAqB,QAAVA,OAAmB,OAAS,OAUzDC,yBAA4BD,QAAWE,SAASF,QACjDG,MAAMC,cACGC,KAAOC,SAASC,cAAcT,yCACpCO,KAAKG,QAAQR,OAASA,OACtBK,KAAKD,MAAQA,MACNC,QAWTI,yBAA4BT,QAAWE,SAASF,QACjDG,MAAMC,cACGM,KAAOJ,SAASC,cAAcT,yCAGpCY,KAAKC,aAAa,QAASP,OAC3BM,KAAKC,aAAa,aAAcP,OAE5BM,KAAKE,QAAQ,QAEbF,KAAKC,aAAa,MAAOE,EAAEC,KAAKC,sBAAef,UAC/CU,KAAKC,aAAa,MAAOP,SAGzBM,KAAKM,UAAUC,IAAIC,aAAalB,SAChCU,KAAKM,UAAUG,OAAOD,aAAanB,eAAeC,WAE/CI,SAWTc,aAAgBlB,QAAsB,QAAVA,OAAoB,eAAiB,SAUjEE,SAAYF,SAAW,0CAA2BA,QAAU,oCAO9C,KAChBM,SAASc,iBAAiB,SAAUC,UAC1BhB,KAAOgB,EAAEC,OAAOV,QAAQd,kCA/Fb,IAACE,OAAQuB,OAgGrBlB,OAGLgB,EAAEG,iBAnGgBxB,OAqGdK,KAAKG,QAAQR,OArGSuB,OAsGtBlB,KAAKG,QAAQe,QAtGoB,iCACzC,oCACU,QAAVvB,OAAmB,EAAI,EACvBuB,QAEHpB,MAAMsB,UACCA,KAAKC,MAAO,OACNC,UAAY5B,eAAeC,QACjCC,yBAAyB0B,WACzBlB,yBAAyBkB,kBAEtBF,QACRG,MAAMC,sBAAaC"}PK\9Lvv'amd/build/change_user_visibility.min.jsnu[define("block_online_users/change_user_visibility",["exports","core/str","core/notification","core_user/repository"],(function(_exports,_str,_notification,_repository){var obj; /** * A javascript module that handles the change of the user's visibility in the * online users block. * * @module block_online_users/change_user_visibility * @copyright 2018 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};const SELECTORS_CHANGE_VISIBILITY_LINK="#change-user-visibility",SELECTORS_CHANGE_VISIBILITY_ICON="#change-user-visibility .icon",oppositeAction=action=>"show"==action?"hide":"show",changeVisibilityLinkAttr=action=>getTitle(action).then((title=>{const link=document.querySelector(SELECTORS_CHANGE_VISIBILITY_LINK);return link.dataset.action=action,link.title=title,link})),changeVisibilityIconAttr=action=>getTitle(action).then((title=>{const icon=document.querySelector(SELECTORS_CHANGE_VISIBILITY_ICON);return icon.setAttribute("title",title),icon.setAttribute("aria-label",title),icon.closest("img")?(icon.setAttribute("src",M.util.image_url("t/".concat(action))),icon.setAttribute("alt",title)):(icon.classList.add(getIconClass(action)),icon.classList.remove(getIconClass(oppositeAction(action)))),title})),getIconClass=action=>"show"==action?"fa-eye-slash":"fa-eye",getTitle=action=>(0,_str.getString)("online_status:".concat(action),"block_online_users");_exports.init=()=>{document.addEventListener("click",(e=>{const link=e.target.closest(SELECTORS_CHANGE_VISIBILITY_LINK);var action,userid;link&&(e.preventDefault(),action=link.dataset.action,userid=link.dataset.userid,(0,_repository.setUserPreference)("block_online_users_uservisibility","show"==action?1:0,userid).then((data=>{if(data.saved){const newAction=oppositeAction(action);changeVisibilityLinkAttr(newAction),changeVisibilityIconAttr(newAction)}return data})).catch(_notification.default.exception))}))}})); //# sourceMappingURL=change_user_visibility.min.js.mapPK\ tests/generator/lib.phpnu[. /** * block_online_users data generator * * @package block_online_users * @category test * @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(); /** * Online users block data generator class * * @package block_online_users * @category test * @copyright 2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class block_online_users_generator extends testing_block_generator { /** * Create (simulated) logged in users and add some of them to groups in a course */ public function create_logged_in_users() { global $DB; $generator = advanced_testcase::getDataGenerator(); $data = array(); // Create 2 courses. $course1 = $generator->create_course(); $data['course1'] = $course1; $course2 = $generator->create_course(); $data['course2'] = $course2; // Create 9 (simulated) logged in users enroled into $course1. for ($i = 1; $i <= 9; $i++) { $user = $generator->create_user(); $DB->set_field('user', 'lastaccess', time(), array('id' => $user->id)); $generator->enrol_user($user->id, $course1->id); $DB->insert_record('user_lastaccess', array('userid' => $user->id, 'courseid' => $course1->id, 'timeaccess' => time())); $data['user' . $i] = $user; } // Create 3 (simulated) logged in users who are not enroled into $course1. for ($i = 10; $i <= 12; $i++) { $user = $generator->create_user(); $DB->set_field('user', 'lastaccess', time(), array('id' => $user->id)); $data['user' . $i] = $user; } // Create 3 groups in course 1. $group1 = $generator->create_group(array('courseid' => $course1->id)); $data['group1'] = $group1; $group2 = $generator->create_group(array('courseid' => $course1->id)); $data['group2'] = $group2; $group3 = $generator->create_group(array('courseid' => $course1->id)); $data['group3'] = $group3; // Add 3 users to course group 1. $generator->create_group_member(array('groupid' => $group1->id, 'userid' => $data['user1']->id)); $generator->create_group_member(array('groupid' => $group1->id, 'userid' => $data['user2']->id)); $generator->create_group_member(array('groupid' => $group1->id, 'userid' => $data['user3']->id)); // Add 4 users to course group 2. $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $data['user3']->id)); $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $data['user4']->id)); $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $data['user5']->id)); $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $data['user6']->id)); return $data; // Return the user, course and group objects. } } PK\eOS99tests/online_users_test.phpnu[. namespace block_online_users; /** * Online users testcase * * @package block_online_users * @category test * @copyright 2015 University of Nottingham * @author Barry Oosthuizen * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class online_users_test extends \advanced_testcase { protected $data; /** * Tests initial setup. * * Prepare the site with some courses, groups, users and * simulate various recent accesses. */ protected function setUp(): void { parent::setUp(); // Generate (simulated) recently logged-in users. $generator = $this->getDataGenerator()->get_plugin_generator('block_online_users'); $this->data = $generator->create_logged_in_users(); // Confirm we have modified the site and requires reset. $this->resetAfterTest(true); } /** * Check logged in group 1, 2 & 3 members in course 1 (should be 3, 4 and 0). * * @param array $data Array of user, course and group objects * @param int $now Current Unix timestamp * @param int $timetoshowusers The time window (in seconds) to check for the latest logged in users */ public function test_fetcher_course1_group_members(): void { global $CFG; $groupid = $this->data['group1']->id; $now = time(); $timetoshowusers = $CFG->block_online_users_timetosee * 60; $context = \context_course::instance($this->data['course1']->id); $courseid = $this->data['course1']->id; $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $usercount = $onlineusers->count_users(); $users = $onlineusers->get_users(); $this->assertEquals(3, $usercount, 'There was a problem counting the number of online users in group 1'); $this->assertEquals($usercount, count($users), 'There was a problem counting the number of online users in group 1'); $groupid = $this->data['group2']->id; $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $usercount = $onlineusers->count_users(); $users = $onlineusers->get_users(); $this->assertEquals($usercount, count($users), 'There was a problem counting the number of online users in group 2'); $this->assertEquals(4, $usercount, 'There was a problem counting the number of online users in group 2'); $groupid = $this->data['group3']->id; $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $usercount = $onlineusers->count_users(); $users = $onlineusers->get_users(); $this->assertEquals($usercount, count($users), 'There was a problem counting the number of online users in group 3'); $this->assertEquals(0, $usercount, 'There was a problem counting the number of online users in group 3'); } /** * Check logged in users in courses 1 & 2 (should be 9 and 0). * * @param array $data Array of user, course and group objects * @param int $now Current Unix timestamp * @param int $timetoshowusers The time window (in seconds) to check for the latest logged in users */ public function test_fetcher_courses(): void { global $CFG; $currentgroup = null; $now = time(); $timetoshowusers = $CFG->block_online_users_timetosee * 60; $context = \context_course::instance($this->data['course1']->id); $courseid = $this->data['course1']->id; $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, false, $courseid); $usercount = $onlineusers->count_users(); $users = $onlineusers->get_users(); $this->assertEquals($usercount, count($users), 'There was a problem counting the number of online users in course 1'); $this->assertEquals(9, $usercount, 'There was a problem counting the number of online users in course 1'); $courseid = $this->data['course2']->id; $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, false, $courseid); $usercount = $onlineusers->count_users(); $users = $onlineusers->get_users(); $this->assertEquals($usercount, count($users), 'There was a problem counting the number of online users in course 2'); $this->assertEquals(0, $usercount, 'There was a problem counting the number of online users in course 2'); } /** * Check logged in at the site level (should be 12). * * @param int $now Current Unix timestamp * @param int $timetoshowusers The time window (in seconds) to check for the latest logged in users */ public function test_fetcher_sitelevel(): void { global $CFG; $currentgroup = null; $now = time(); $timetoshowusers = $CFG->block_online_users_timetosee * 60; $context = \context_system::instance(); $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, true); $usercount = $onlineusers->count_users(); $users = $onlineusers->get_users(); $this->assertEquals($usercount, count($users), 'There was a problem counting the number of online users at site level'); $this->assertEquals(12, $usercount, 'There was a problem counting the number of online users at site level'); } /** * Check user visibility setting for course group members. */ public function test_user_visibility_course1_group1_members(): void { global $CFG; // Enable users to set their visibility to others in the online users block. $CFG->block_online_users_onlinestatushiding = true; $groupid = $this->data['group1']->id; $now = time(); $timetoshowusers = $CFG->block_online_users_timetosee * 60; $context = \context_course::instance($this->data['course1']->id); $courseid = $this->data['course1']->id; $user1 = $this->data['user1']; $user2 = $this->data['user2']; // Set user2 as logged user. $this->setUser($user2); $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(3, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); // Set user1 as logged user. $this->setUser($user1); // Set visibility to 'hide' for user1. set_user_preference('block_online_users_uservisibility', 0); // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(3, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); // Set user2 as logged user. $this->setUser($user2); // Test if the fetcher gets all the users excluding user1. $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should not be displayed in the online users block. $this->assertEquals(2, $usercount); $this->assertFalse(array_key_exists($user1->id, $users)); // Disable users to set their visibility to others in the online users block. // All users should be displayed now and the visibility status of a users should be ignored, // as the capability of setting the visibility to other user has been disabled. $CFG->block_online_users_onlinestatushiding = false; // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($groupid, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(3, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); } /** * Check user visibility setting at course level. */ public function test_user_visibility_courses(): void { global $CFG; $currentgroup = null; $now = time(); $timetoshowusers = $CFG->block_online_users_timetosee * 60; $context = \context_course::instance($this->data['course1']->id); $courseid = $this->data['course1']->id; $user1 = $this->data['user1']; $user2 = $this->data['user2']; // Set user2 as logged user. $this->setUser($user2); // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(9, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); // Set user1 as logged user. $this->setUser($user1); // Set visibility to 'hide' for user1. set_user_preference('block_online_users_uservisibility', 0); // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(9, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); // Set user2 as logged user. $this->setUser($user2); // Test if the fetcher gets all the users excluding user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should not be displayed in the online users block. $this->assertEquals(8, $usercount); $this->assertFalse(array_key_exists($user1->id, $users)); // Disable users to set their visibility to others in the online users block. // All users should be displayed now and the visibility status of a users should be ignored, // as the capability of setting the visibility to other user has been disabled. $CFG->block_online_users_onlinestatushiding = false; // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, false, $courseid); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(9, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); } /** * Check user visibility setting at site level. */ public function test_user_visibility_sitelevel(): void { global $CFG; $currentgroup = null; $now = time(); $timetoshowusers = $CFG->block_online_users_timetosee * 60; $context = \context_system::instance(); $user1 = $this->data['user1']; $user2 = $this->data['user2']; // Set user2 as logged user. $this->setUser($user2); // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, true); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(12, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); // Set user1 as logged user. $this->setUser($user1); // Set visibility to 'hide' for user1. set_user_preference('block_online_users_uservisibility', 0); // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, true); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(12, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); // Set user2 as logged user. $this->setUser($user2); // Test if the fetcher gets all the users excluding user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, true); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should not be displayed in the online users block. $this->assertEquals(11, $usercount); $this->assertFalse(array_key_exists($user1->id, $users)); // Disable users to set their visibility to others in the online users block. // All users should be displayed now and the visibility status of a users should be ignored, // as the capability of setting the visibility to other user has been disabled. $CFG->block_online_users_onlinestatushiding = false; // Test if the fetcher gets all the users including user1. $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $context, true); $users = $onlineusers->get_users(); $usercount = $onlineusers->count_users(); // User1 should be displayed in the online users block. $this->assertEquals(12, $usercount); $this->assertTrue(array_key_exists($user1->id, $users)); } } PK\- Otests/generator_test.phpnu[. namespace block_online_users; /** * PHPUnit data generator testcase * * @package block_online_users * @category phpunit * @copyright 2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class generator_test extends \advanced_testcase { public function test_generator(): void { global $DB; $this->resetAfterTest(true); $beforeblocks = $DB->count_records('block_instances'); $beforecontexts = $DB->count_records('context'); /** @var \block_online_users_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('block_online_users'); $this->assertInstanceOf('block_online_users_generator', $generator); $this->assertEquals('online_users', $generator->get_blockname()); $generator->create_instance(); $generator->create_instance(); $bi = $generator->create_instance(); $this->assertEquals($beforeblocks+3, $DB->count_records('block_instances')); } } PK\؈dd-tests/behat/block_online_users_course.featurenu[@block @block_online_users Feature: The online users block allow you to see who is currently online In order to enable the online users block on an course page As a teacher I can add the online users block to a course page Background: Given the following "courses" exist: | fullname | shortname | category | | Course 1 | C1 | 0 | And the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@example.com | | student1 | Student | 1 | student1@example.com | | student2 | Student | 2 | student2@example.com | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | | student1 | C1 | student | Scenario: Add the online users on course page and see myself Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on When I add the "Online users" block Then I should see "Teacher 1" in the "Online users" "block" And I should see "1 online user" in the "Online users" "block" Scenario: Add the online users on course page and see other logged in users Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on And I add the "Online users" block And I log out And I log in as "student2" And I log out When I log in as "student1" And I am on "Course 1" course homepage Then I should see "Teacher 1" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And I should not see "Student 2" in the "Online users" "block" And I should see "2 online users" in the "Online users" "block" @javascript Scenario: Hide/show user's online status from/to other users in the online users block on course page Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on And I add the "Online users" block And I log out When I log in as "student1" And I am on "Course 1" course homepage Then "Hide" "icon" should exist in the "#change-user-visibility" "css_element" When I click on "#change-user-visibility" "css_element" And I wait "1" seconds Then "Show" "icon" should exist in the "#change-user-visibility" "css_element" And I log out When I log in as "teacher1" And I am on "Course 1" course homepage Then I should see "1 online user" in the "Online users" "block" And I should see "Teacher 1" in the "Online users" "block" And I should not see "Student 1" in the "Online users" "block" And I log out When I log in as "student1" And I am on "Course 1" course homepage Then "Show" "icon" should exist in the "#change-user-visibility" "css_element" When I click on "#change-user-visibility" "css_element" And I wait "1" seconds Then "Hide" "icon" should exist in the "#change-user-visibility" "css_element" And I log out When I log in as "teacher1" And I am on "Course 1" course homepage Then I should see "2 online users" in the "Online users" "block" And I should see "Teacher 1" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" @javascript Scenario: Hide/show icon is not visible in the online users block on course page when the setting is disabled Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on And I add the "Online users" block And I log out And I log in as "student1" And I am on "Course 1" course homepage And "Hide" "icon" should exist in the ".block.block_online_users" "css_element" And I log out And the following config values are set as admin: | block_online_users_onlinestatushiding | 0 | When I log in as "student1" And I am on "Course 1" course homepage Then I should see "Student 1" in the "Online users" "block" And "Hide" "icon" should not exist in the ".block.block_online_users" "css_element" @javascript Scenario: User is displayed in the online users block on course page when visibility setting is disabled, ignoring the previously set visibility state Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on And I add the "Online users" block And I log out And I log in as "student1" And I am on "Course 1" course homepage And "Hide" "icon" should exist in the "#change-user-visibility" "css_element" And I click on "#change-user-visibility" "css_element" And I wait "1" seconds And "Show" "icon" should exist in the "#change-user-visibility" "css_element" And I log out And the following config values are set as admin: | block_online_users_onlinestatushiding | 0 | And I log in as "teacher1" When I am on "Course 1" course homepage Then I should see "2 online users" in the "Online users" "block" And I should see "Teacher 1" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" PK\e0tests/behat/block_online_users_frontpage.featurenu[@block @block_online_users Feature: The online users block allow you to see who is currently online on frontpage There should be some commonality for the users to show up In order to enable the online users block on the frontpage As an admin I can add the online users block to the frontpage Background: Given the following "users" exist: | username | firstname | lastname | email | | student1 | Student | 1 | student1@example.com | | student2 | Student | 2 | student2@example.com | And the following "courses" exist: | fullname | shortname | category | | Course 1 | C1 | 0 | And the following "course enrolments" exist: | user | course | role | | student1 | C1 | student | | student2 | C1 | student | Scenario: View the online users block on the front page and see myself Given I log in as "admin" And I am on site homepage And I turn editing mode on When I add the "Online users" block Then I should see "Admin User" in the "Online users" "block" And I should see "1 online user" in the "Online users" "block" Scenario: View the online users block on the front page as a logged in user Given I log in as "admin" And I am on site homepage And I turn editing mode on And I add the "Online users" block And I log out And I log in as "student2" And I log out When I log in as "student1" And I am on site homepage Then I should not see "Admin User" in the "Online users" "block" And I should see "Other users (1)" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should see "3 online users" in the "Online users" "block" Scenario: View the online users block on the front page as a guest Given I log in as "admin" And I am on site homepage And I turn editing mode on And I add the "Online users" block And I log out And I log in as "student2" And I log out And I log in as "student1" And I log out When I log in as "guest" And I am on site homepage Then I should not see "Admin User" in the "Online users" "block" And I should not see "Student 1" in the "Online users" "block" And I should not see "Student 2" in the "Online users" "block" And I should see "3 online users" in the "Online users" "block" @javascript Scenario: Hide/show user's online status from/to other users in the online users block on front page Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "admin" And I am on site homepage And I turn editing mode on And I add the "Online users" block And I log out When I log in as "student1" And I am on site homepage Then "Hide" "icon" should exist in the "#change-user-visibility" "css_element" When I click on "#change-user-visibility" "css_element" And I wait "1" seconds Then "Show" "icon" should exist in the "#change-user-visibility" "css_element" And I log out When I log in as "student2" And I am on site homepage Then I should see "2 online user" in the "Online users" "block" And I should not see "Admin" in the "Online users" "block" And I should see "Other users (1)" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should not see "Student 1" in the "Online users" "block" And I log out When I log in as "student1" And I am on site homepage Then "Show" "icon" should exist in the "#change-user-visibility" "css_element" When I click on "#change-user-visibility" "css_element" And I wait "1" seconds Then "Hide" "icon" should exist in the "#change-user-visibility" "css_element" And I log out When I log in as "student2" And I am on site homepage Then I should see "3 online users" in the "Online users" "block" And I should not see "Admin" in the "Online users" "block" And I should see "Other users (1)" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" @javascript Scenario: Hide/show icon is not visible in the online users block on front page when the setting is disabled Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "admin" And I am on site homepage And I turn editing mode on And I add the "Online users" block And I log out And I log in as "student1" And I am on site homepage And "Hide" "icon" should exist in the ".block.block_online_users" "css_element" And I log out And the following config values are set as admin: | block_online_users_onlinestatushiding | 0 | When I log in as "student1" And I am on site homepage Then I should see "Student 1" in the "Online users" "block" And "Hide" "icon" should not exist in the ".block.block_online_users" "css_element" @javascript Scenario: User is displayed in the online users block on front page when visibility setting is disabled, ignoring the previously set visibility state Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "admin" And I am on site homepage And I turn editing mode on And I add the "Online users" block And I log out And I log in as "student1" And I am on site homepage And "Hide" "icon" should exist in the "#change-user-visibility" "css_element" And I click on "#change-user-visibility" "css_element" And I wait "1" seconds And "Show" "icon" should exist in the "#change-user-visibility" "css_element" And I log out And I log in as "student2" And I am on site homepage And I should see "2 online user" in the "Online users" "block" And I should not see "Admin" in the "Online users" "block" And I should see "Other users (1)" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should not see "Student 1" in the "Online users" "block" And I log out And the following config values are set as admin: | block_online_users_onlinestatushiding | 0 | And I log in as "student2" When I am on site homepage Then I should see "3 online users" in the "Online users" "block" And I should not see "Admin" in the "Online users" "block" And I should see "Other users (1)" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" PK\Nu<<0tests/behat/block_online_users_dashboard.featurenu[@block @block_online_users Feature: The online users block allow you to see who is currently online on dashboard There should be some commonality for the users to show up In order to use the online users block on the dashboard As a user I can view the online users block on my dashboard Background: Given the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@example.com | | student1 | Student | 1 | student1@example.com | | student2 | Student | 2 | student2@example.com | And the following "courses" exist: | fullname | shortname | category | | Course 1 | C1 | 0 | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | | student1 | C1 | student | | student2 | C1 | student | And the following "blocks" exist: | blockname | contextlevel | reference | pagetypepattern | defaultregion | | online_users | System | 1 | my-index | side-post | Scenario: View the online users block on the dashboard and see myself Given I log in as "teacher1" Then I should see "Teacher 1" in the "Online users" "block" And I should see "1 online user" in the "Online users" "block" Scenario: View the online users block on the dashboard and see other logged in users Given I log in as "student2" And I log out And I log in as "student1" And I log out When I log in as "teacher1" Then I should see "Teacher 1" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should see "3 online users" in the "Online users" "block" @javascript Scenario: Hide/show user's online status from/to other users in the online users block on dashboard Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "student1" And I should see "1 online user" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And "Hide" "icon" should exist in the "#change-user-visibility" "css_element" When I click on "#change-user-visibility" "css_element" And I wait "1" seconds Then "Show" "icon" should exist in the "#change-user-visibility" "css_element" And I log out When I log in as "student2" Then I should see "1 online user" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should not see "Student 1" in the "Online users" "block" And I log out When I log in as "student1" Then "Show" "icon" should exist in the "#change-user-visibility" "css_element" When I click on "#change-user-visibility" "css_element" And I wait "1" seconds Then "Hide" "icon" should exist in the "#change-user-visibility" "css_element" And I log out When I log in as "student2" Then I should see "2 online users" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" @javascript Scenario: Hide/show icon is not visible in the online users block when the setting is disabled Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "student1" And I should see "1 online user" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And "Hide" "icon" should exist in the ".block.block_online_users" "css_element" And I log out And the following config values are set as admin: | block_online_users_onlinestatushiding | 0 | When I log in as "student1" Then I should see "1 online user" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And "Hide" "icon" should not exist in the ".block.block_online_users" "css_element" @javascript Scenario: User is displayed in the online users block when visibility setting is disabled, ignoring the previously set visibility state Given the following config values are set as admin: | block_online_users_onlinestatushiding | 1 | And I log in as "student1" And I should see "1 online user" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" And "Hide" "icon" should exist in the "#change-user-visibility" "css_element" And I click on "#change-user-visibility" "css_element" And I wait "1" seconds And "Show" "icon" should exist in the "#change-user-visibility" "css_element" And I log out And I log in as "student2" And I should see "1 online user" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should not see "Student 1" in the "Online users" "block" And I log out And the following config values are set as admin: | block_online_users_onlinestatushiding | 0 | When I log in as "student2" Then I should see "2 online users" in the "Online users" "block" And I should see "Student 2" in the "Online users" "block" And I should see "Student 1" in the "Online users" "block" PK\ѥ""block_online_users.phpnu[. /** * Online users block. * * @package block_online_users * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ use block_online_users\fetcher; /** * This block needs to be reworked. * The new roles system does away with the concepts of rigid student and * teacher roles. */ class block_online_users extends block_base { function init() { $this->title = get_string('pluginname','block_online_users'); } function has_config() { return true; } function get_content() { global $USER, $CFG, $DB, $OUTPUT; if ($this->content !== NULL) { return $this->content; } $this->content = new stdClass; $this->content->text = ''; $this->content->footer = ''; if (empty($this->instance)) { return $this->content; } $timetoshowusers = 300; //Seconds default if (isset($CFG->block_online_users_timetosee)) { $timetoshowusers = $CFG->block_online_users_timetosee * 60; } $now = time(); //Calculate if we are in separate groups $isseparategroups = ($this->page->course->groupmode == SEPARATEGROUPS && $this->page->course->groupmodeforce && !has_capability('moodle/site:accessallgroups', $this->page->context)); //Get the user current group $currentgroup = $isseparategroups ? groups_get_course_group($this->page->course) : NULL; $sitelevel = $this->page->course->id == SITEID || $this->page->context->contextlevel < CONTEXT_COURSE; $onlineusers = new fetcher($currentgroup, $now, $timetoshowusers, $this->page->context, $sitelevel, $this->page->course->id); //Calculate minutes $minutes = floor($timetoshowusers/60); $periodminutes = get_string('periodnminutes', 'block_online_users', $minutes); // Count users. $usercount = $onlineusers->count_users(); if ($usercount === 0) { $usercount = get_string('nouser', 'block_online_users'); } else if ($usercount === 1) { $usercount = get_string('numuser', 'block_online_users', $usercount); } else { $usercount = get_string('numusers', 'block_online_users', $usercount); } $this->content->text = '
'.$usercount.' ('.$periodminutes.')
'; // Verify if we can see the list of users, if not just print number of users. // If the current user is not logged in OR it's a guest then don't show any users. if (!has_capability('block/online_users:viewlist', $this->page->context) || isguestuser() || !isloggedin()) { return $this->content; } $userlimit = 50; // We'll just take the most recent 50 maximum. $initialcount = 0; if ($users = $onlineusers->get_users($userlimit)) { require_once($CFG->dirroot . '/user/lib.php'); $initialcount = count($users); foreach ($users as $user) { if (!user_can_view_profile($user)) { unset($users[$user->id]); continue; } $users[$user->id]->fullname = fullname($user); } } else { $users = array(); } //Now, we have in users, the list of users to show //Because they are online if (!empty($users)) { $this->page->requires->js_call_amd('block_online_users/change_user_visibility', 'init'); //Accessibility: Don't want 'Alt' text for the user picture; DO want it for the envelope/message link (existing lang string). //Accessibility: Converted
to
    , inherit existing classes & styles. $this->content->text .= "
      \n"; if (isloggedin() && has_capability('moodle/site:sendmessage', $this->page->context) && !empty($CFG->messaging) && !isguestuser()) { $canshowicon = true; } else { $canshowicon = false; } foreach ($users as $user) { $this->content->text .= '
    • '; $timeago = format_time($now - $user->lastaccess); //bruno to calculate correctly on frontpage if (isguestuser($user)) { $this->content->text .= '
      '.$OUTPUT->user_picture($user, array('size'=>16, 'alttext'=>false)); $this->content->text .= get_string('guestuser').'
      '; } else { // Not a guest user. $this->content->text .= ''; if ($USER->id == $user->id) { if ($CFG->block_online_users_onlinestatushiding) { $action = ($user->uservisibility != null && $user->uservisibility == 0) ? 'show' : 'hide'; $anchortagcontents = $OUTPUT->pix_icon('t/' . $action, get_string('online_status:' . $action, 'block_online_users')); $anchortag = html_writer::link("", $anchortagcontents, array('title' => get_string('online_status:' . $action, 'block_online_users'), 'data-action' => $action, 'data-userid' => $user->id, 'id' => 'change-user-visibility')); $this->content->text .= '
      ' . $anchortag . '
      '; } } else { if ($canshowicon) { // Only when logged in and messaging active etc. $anchortagcontents = $OUTPUT->pix_icon('t/message', get_string('messageselectadd')); $anchorurl = new moodle_url('/message/index.php', array('id' => $user->id)); $anchortag = html_writer::link($anchorurl, $anchortagcontents, array('title' => get_string('messageselectadd'))); $this->content->text .= '
      '.$anchortag.'
      '; } } } $this->content->text .= "
    • \n"; } if ($initialcount - count($users) > 0) { $this->content->text .= '
    • '; $this->content->text .= html_writer::span( get_string('otherusers', 'block_online_users', $initialcount - count($users)) ); $this->content->text .= "
      "; $this->content->text .= "
    • \n"; } $this->content->text .= '
    '; } return $this->content; } /** * Return the plugin config settings for external functions. * * @return stdClass the configs for both the block instance and plugin * @since Moodle 3.8 */ public function get_config_for_external() { global $CFG; // Return all settings for all users since it is safe (no private keys, etc..). $configs = (object) [ 'timetosee' => $CFG->block_online_users_timetosee, 'onlinestatushiding' => $CFG->block_online_users_onlinestatushiding ]; return (object) [ 'instance' => new stdClass(), 'plugin' => $configs, ]; } } PK\INVĒ settings.phpnu[. /** * Online users block settings. * * @package block_online_users * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { $settings->add(new admin_setting_configtext('block_online_users_timetosee', get_string('timetosee', 'block_online_users'), get_string('configtimetosee', 'block_online_users'), 5, PARAM_INT)); $settings->add(new admin_setting_configcheckbox('block_online_users_onlinestatushiding', get_string('onlinestatushiding', 'block_online_users'), get_string('onlinestatushiding_desc', 'block_online_users'), 1)); } PK\B|ï styles.cssnu[PK\G:&G db/access.phpnu[PK\ W~,, lang/en/block_online_users.phpnu[PK\i Ulib.phpnu[PK\1 _ 8version.phpnu[PK\i classes/privacy/provider.phpnu[PK\<0(classes/fetcher.phpnu[PK\SCC!hGamd/src/change_user_visibility.jsnu[PK\6z^DD+Xamd/build/change_user_visibility.min.js.mapnu[PK\9Lvv'pamd/build/change_user_visibility.min.jsnu[PK\ hytests/generator/lib.phpnu[PK\eOS99tests/online_users_test.phpnu[PK\- Otests/generator_test.phpnu[PK\؈dd-tests/behat/block_online_users_course.featurenu[PK\e0tests/behat/block_online_users_frontpage.featurenu[PK\Nu<<0tests/behat/block_online_users_dashboard.featurenu[PK\ѥ""tblock_online_users.phpnu[PK\INVĒ 3settings.phpnu[PKbN9