MDL-6074 blocks: Hide user in online users block
authorMihail Geshoski <mihail@moodle.com>
Wed, 13 Jun 2018 01:02:24 +0000 (09:02 +0800)
committerMihail Geshoski <mihail@moodle.com>
Wed, 13 Jun 2018 01:02:24 +0000 (09:02 +0800)
14 files changed:
blocks/online_users/amd/build/change_user_visibility.min.js [new file with mode: 0644]
blocks/online_users/amd/src/change_user_visibility.js [new file with mode: 0644]
blocks/online_users/block_online_users.php
blocks/online_users/classes/fetcher.php
blocks/online_users/classes/privacy/provider.php
blocks/online_users/lang/en/block_online_users.php
blocks/online_users/lib.php [new file with mode: 0644]
blocks/online_users/styles.css
blocks/online_users/tests/behat/block_online_users_course.feature
blocks/online_users/tests/behat/block_online_users_dashboard.feature
blocks/online_users/tests/behat/block_online_users_frontpage.feature
blocks/online_users/tests/online_users_test.php
blocks/online_users/version.php
lib/db/services.php

diff --git a/blocks/online_users/amd/build/change_user_visibility.min.js b/blocks/online_users/amd/build/change_user_visibility.min.js
new file mode 100644 (file)
index 0000000..f45ae5b
Binary files /dev/null and b/blocks/online_users/amd/build/change_user_visibility.min.js differ
diff --git a/blocks/online_users/amd/src/change_user_visibility.js b/blocks/online_users/amd/src/change_user_visibility.js
new file mode 100644 (file)
index 0000000..4fbed82
--- /dev/null
@@ -0,0 +1,171 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * A javascript module that handles the change of the user's visibility in the
+ * online users block.
+ *
+ * @module     block_online_users/change_user_visibility
+ * @package    block_online_users
+ * @copyright  2018 Mihail Geshoski <mihail@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/ajax', 'core/str', 'core/notification'],
+        function($, Ajax, Str, Notification) {
+
+    /**
+     * Selectors.
+     *
+     * @access private
+     * @type {Object}
+     */
+    var 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
+     * @private
+     */
+    var changeVisibility = function(action, userid) {
+
+        var value = action == "show" ? 1 : 0;
+        var preferences = [{
+            'name': 'block_online_users_uservisibility',
+            'value': value,
+            'userid': userid
+        }];
+
+        var request = {
+            methodname: 'core_user_set_user_preferences',
+            args: {
+                preferences: preferences
+            }
+        };
+        Ajax.call([request])[0].then(function(data) {
+            if (data.saved) {
+                var newAction = oppositeAction(action);
+                changeVisibilityLinkAttr(newAction);
+                changeVisibilityIconAttr(newAction);
+            }
+            return;
+        }).catch(Notification.exception);
+    };
+
+    /**
+     * Get the opposite action.
+     *
+     * @method oppositeAction
+     * @param {String} action
+     * @return {String}
+     * @private
+     */
+    var oppositeAction = function(action) {
+        return action == 'show' ? 'hide' : 'show';
+    };
+
+    /**
+     * Change the attribute values of the user visibility link in the online users block.
+     *
+     * @method changeVisibilityLinkAttr
+     * @param {String} action
+     * @private
+     */
+    var changeVisibilityLinkAttr = function(action) {
+        getTitle(action).then(function(title) {
+            $(SELECTORS.CHANGE_VISIBILITY_LINK).attr({
+                'data-action': action,
+                'title': title
+            });
+            return;
+        }).catch(Notification.exception);
+    };
+
+    /**
+     * Change the attribute values of the user visibility icon in the online users block.
+     *
+     * @method changeVisibilityIconAttr
+     * @param {String} action
+     * @private
+     */
+    var changeVisibilityIconAttr = function(action) {
+        var icon = $(SELECTORS.CHANGE_VISIBILITY_ICON);
+        getTitle(action).then(function(title) {
+            // Add the proper title to the icon.
+            $(icon).attr({
+                'title': title,
+                'aria-label': title
+            });
+            // If the icon is an image.
+            if (icon.is("img")) {
+                $(icon).attr({
+                    'src': M.util.image_url('t/' + action),
+                    'alt': title
+                });
+            } else {
+                // Add the new icon class and remove the old one.
+                $(icon).addClass(getIconClass(action));
+                $(icon).removeClass(getIconClass(oppositeAction(action)));
+            }
+            return;
+        }).catch(Notification.exception);
+    };
+
+    /**
+     * Get the proper class for the user visibility icon in the online users block.
+     *
+     * @method getIconClass
+     * @param {String} action
+     * @return {String}
+     * @private
+     */
+    var getIconClass = function(action) {
+        return 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
+     */
+    var getTitle = function(action) {
+        return Str.get_string('online_status:' + action, 'block_online_users');
+    };
+
+    return {
+        // Public variables and functions.
+        /**
+         * Initialise change user visibility function.
+         *
+         * @method init
+         */
+        init: function() {
+            $(SELECTORS.CHANGE_VISIBILITY_LINK).on('click', function(e) {
+                e.preventDefault();
+                var action = ($(this).attr('data-action'));
+                var userid = ($(this).attr('data-userid'));
+                changeVisibility(action, userid);
+            });
+        }
+    };
+});
index 08521a3..01ada95 100644 (file)
@@ -105,6 +105,7 @@ class block_online_users extends block_base {
         //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 <div> to <ul>, inherit existing classes & styles.
             $this->content->text .= "<ul class='list'>\n";
@@ -122,18 +123,30 @@ class block_online_users extends block_base {
                     $this->content->text .= '<div class="user">'.$OUTPUT->user_picture($user, array('size'=>16, 'alttext'=>false));
                     $this->content->text .= get_string('guestuser').'</div>';
 
-                } else {
+                } else { // Not a guest user.
                     $this->content->text .= '<div class="user">';
                     $this->content->text .= '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$this->page->course->id.'" title="'.$timeago.'">';
                     $this->content->text .= $OUTPUT->user_picture($user, array('size'=>16, 'alttext'=>false, 'link'=>false)) .$user->fullname.'</a></div>';
-                }
-                if ($canshowicon and ($USER->id != $user->id) and !isguestuser($user)) {  // 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 .= '<div class="message">'.$anchortag.'</div>';
+                    if ($USER->id == $user->id) {
+                        $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 .= '<div class="uservisibility">' . $anchortag . '</div>';
+                    } 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 .= '<div class="message">'.$anchortag.'</div>';
+                        }
+                    }
                 }
                 $this->content->text .= "</li>\n";
             }
index 1c6d15a..20f706f 100644 (file)
@@ -67,6 +67,8 @@ class fetcher {
      * @param int $courseid The course id to check
      */
     protected function set_sql($currentgroup, $now, $timetoshowusers, $context, $sitelevel, $courseid) {
+        global $USER, $DB;
+
         $timefrom = 100 * floor(($now - $timetoshowusers) / 100); // Round to nearest 100 seconds for better query cache.
 
         $groupmembers = "";
@@ -74,6 +76,7 @@ class fetcher {
         $groupby       = "";
         $lastaccess    = ", lastaccess";
         $timeaccess    = ", ul.timeaccess AS lastaccess";
+        $uservisibility = ", up.value AS uservisibility";
         $params = array();
 
         $userfields = \user_picture::fields('u', array('username'));
@@ -85,52 +88,75 @@ class fetcher {
             $groupby = "GROUP BY $userfields";
             $lastaccess = ", MAX(u.lastaccess) AS lastaccess";
             $timeaccess = ", MAX(ul.timeaccess) AS lastaccess";
+            $uservisibility = ", MAX(up.value) 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
+            $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
+                           AND (" . $DB->sql_cast_char2int('up.value') . " = 1
+                               OR up.value IS NULL
+                               OR u.id = :userid)
                            $groupselect $groupby
                   ORDER BY lastaccess DESC ";
 
             $csql = "SELECT COUNT(u.id)
-                      FROM {user} u $groupmembers
-                     WHERE u.lastaccess > :timefrom
-                           AND u.lastaccess <= :now
-                           AND u.deleted = 0
-                           $groupselect";
-
+                       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
+                            AND (" . $DB->sql_cast_char2int('up.value') . " = 1
+                                OR up.value IS NULL
+                                OR u.id = :userid)
+                            $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
+            $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
+                           AND (" . $DB->sql_cast_char2int('up.value') . " = 1
+                               OR up.value IS NULL
+                               OR u.id = :userid)
                            $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
+                           AND (" . $DB->sql_cast_char2int('up.value') . " = 1
+                               OR up.value IS NULL
+                               OR u.id = :userid)
                            $groupselect";
 
             $params['courseid'] = $courseid;
index 50d0280..3f29a8e 100644 (file)
 
 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 implementing null_provider.
+ * Privacy Subsystem for block_online_users.
  *
  * @copyright  2018 Zig Tan <zig@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class provider implements \core_privacy\local\metadata\null_provider {
+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;
+    }
 
     /**
-     * Get the language string identifier with the component's language
-     * file to explain why this plugin stores no data.
+     * Export user preferences controlled by this plugin.
      *
-     * @return  string
+     * @param int $userid ID of the user we are exporting data form.
      */
-    public static function get_reason() : string {
-        return 'privacy:metadata';
+    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'));
     }
 }
index ff79ce5..c6bc022 100644 (file)
@@ -30,7 +30,9 @@ $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'] = 'The Online users block only shows data stored in other locations.';
+$string['privacy:metadata:preference:uservisibility'] = 'Online status visible to other users in the Online users block.';
diff --git a/blocks/online_users/lib.php b/blocks/online_users/lib.php
new file mode 100644 (file)
index 0000000..0c76080
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Contains functions called by core.
+ *
+ * @package    block_online_users
+ * @copyright  2018 Mihail Geshoski <mihail@moodle.com>
+ * @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;
+}
index 90be203..bebee5a 100644 (file)
@@ -11,7 +11,8 @@
     vertical-align: text-bottom;
 }
 
-.block_online_users .content .list li.listentry .message {
+.block_online_users .content .list li.listentry .message,
+.block_online_users .content .list li.listentry .uservisibility {
     float: right;
     margin-top: 3px;
 }
index e86e4d8..20b0d95 100644 (file)
@@ -39,3 +39,35 @@ Feature: The online users block allow you to see who is currently online
     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 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"
index 34207c5..0d01207 100644 (file)
@@ -26,3 +26,29 @@ Feature: The online users block allow you to see who is currently online on dash
     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 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"
index 6237d3d..0c5bbdd 100644 (file)
@@ -49,3 +49,38 @@ Feature: The online users block allow you to see who is currently online on fron
     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 front page
+    Given I log in as "admin"
+    And I am on site homepage
+    And I navigate to "Turn editing on" node in "Front page settings"
+    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 see "Admin" 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 see "Admin" 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"
index 9ff1e3c..946e456 100644 (file)
@@ -148,4 +148,134 @@ class block_online_users_testcase extends advanced_testcase {
         $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() {
+        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;
+        $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));
+    }
+
+    /**
+     * Check user visibility setting at course level.
+     */
+    public function test_user_visibility_courses() {
+        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));
+    }
+
+    /**
+     * Check user visibility setting at site level.
+     */
+    public function test_user_visibility_sitelevel() {
+        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));
+    }
 }
index 6bbce9f..1db749f 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2018051400;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2018051401;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2018050800;        // Requires this Moodle version
 $plugin->component = 'block_online_users'; // Full name of the plugin (used for diagnostics)
index 9761089..3493fca 100644 (file)
@@ -1353,6 +1353,7 @@ $functions = array(
         'description' => 'Set user preferences.',
         'type' => 'write',
         'capabilities' => 'moodle/site:config',
+        'ajax' => true
     ),
     'core_user_agree_site_policy' => array(
         'classname' => 'core_user_external',