Skip to content

Commit

Permalink
MDL-74296 mod_bigbluebuttonbn: Fix completion indicator
Browse files Browse the repository at this point in the history
* Completion view should work out of the box
* Patch the _user_outline and _user_complete so it works with completion view, while
implementing something better in MDL-74468
  • Loading branch information
laurentdavid committed Jun 10, 2022
1 parent 4a9fa42 commit d9a62c9
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 75 deletions.
32 changes: 2 additions & 30 deletions mod/bigbluebuttonbn/classes/completion/custom_completion.php
Expand Up @@ -48,8 +48,7 @@ public function get_state(string $rule): int {

// Default return value.
$value = COMPLETION_INCOMPLETE;
$filters = $rule != "completionview" ? [logger::EVENT_SUMMARY] : [logger::EVENT_JOIN, logger::EVENT_PLAYED];
$logs = logger::get_user_completion_logs($instance, $this->userid, $filters);
$logs = logger::get_user_completion_logs($instance, $this->userid, [logger::EVENT_SUMMARY]);

if (method_exists($this, "get_{$rule}_value")) {
$valuecount = $this->count_actions($logs, self::class . "::get_{$rule}_value");
Expand Down Expand Up @@ -101,8 +100,6 @@ public static function get_defined_custom_rules(): array {
'completionengagementraisehand',
'completionengagementpollvotes',
'completionengagementemojis',
'completionview' // Completion view is now a customrule as it depends on the logs and not
// the view action itself.
];
}

Expand Down Expand Up @@ -141,7 +138,6 @@ public function get_custom_rule_descriptions(): array {
*/
public function get_sort_order(): array {
return [
'completionview',
'completionengagementchats',
'completionengagementtalks',
'completionengagementraisehand',
Expand All @@ -166,8 +162,7 @@ public function get_printable_state(string $rule): string {
}

$summary = "";
$filters = $rule != "completionview" ? [logger::EVENT_SUMMARY] : [logger::EVENT_JOIN, logger::EVENT_PLAYED];
$logs = logger::get_user_completion_logs($instance, $this->userid, $filters);
$logs = logger::get_user_completion_logs($instance, $this->userid, [logger::EVENT_SUMMARY]);

if (method_exists($this, "get_{$rule}_value")) {
$summary = get_string(
Expand Down Expand Up @@ -196,29 +191,6 @@ public function get_last_log_timestamp(string $rule): string {
return logger::get_user_completion_logs_max_timestamp($instance, $this->userid, $filters);
}

/**
* Fetches the list of custom completion rules that are being used by this activity module instance.
*
* @return array
*/
public function get_available_custom_rules(): array {
$availablerules = parent::get_available_custom_rules();
$availablerules[] = 'completionview'; // Completion view is now a customrule.
return $availablerules;
}

/**
* Get completion view value
*
* This will override the usual completion value (see COMPLETION_CUSTOM_MODULE_FLOW)
*
* @param stdClass $log
* @return int
*/
protected static function get_completionview_value(stdClass $log): int {
return $log->log == logger::EVENT_PLAYED || $log->log == logger::EVENT_JOIN;
}

/**
* Get attendance summary value
*
Expand Down
73 changes: 73 additions & 0 deletions mod/bigbluebuttonbn/classes/local/helpers/user_info.php
@@ -0,0 +1,73 @@
<?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/>.
namespace mod_bigbluebuttonbn\local\helpers;

use cm_info;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\logger;
use stdClass;

/**
* Utility class for all user information
*
* Used mainly in user_outline and user_complete
*
* @package mod_bigbluebuttonbn
* @copyright 2022 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent [at] call-learning [dt] fr)
*/
class user_info {
/**
* Event to watch for.
*/
const EVENT_TO_WATCH = [
'join' => logger::EVENT_JOIN,
'play_recording' => logger::EVENT_PLAYED
];

/**
* Get user outline and complete info
*
* @param stdClass $course
* @param stdClass $user
* @param cm_info $mod
* @return array[] an array of infos and timestamps (latest timestamp)
*/
public static function get_user_info_outline(stdClass $course, stdClass $user, cm_info $mod): array {
$completion = new \completion_info($course);
$cdata = $completion->get_data($mod, false, $user->id);
$logtimestamps = [];
$infos = [];
if (!empty($cdata->viewed) && $cdata->viewed) {
$infos[] = get_string('report_room_view', 'mod_bigbluebuttonbn');
$logtimestamps[] = $cdata->timemodified;
}
$instance = instance::get_from_cmid($mod->id);
foreach (self::EVENT_TO_WATCH as $eventtype => $logtype) {
$logs = logger::get_user_completion_logs($instance, $user->id, [$logtype]);
if ($logs) {
$infos[] = get_string("report_{$eventtype}_info", 'mod_bigbluebuttonbn', count($logs));
$latesttime = array_reduce($logs,
function($acc, $log) {
return ($acc > $log->timecreated) ? $acc : $log->timecreated;
}, 0);
$logtimestamps[] = $latesttime;
}
}
return [$infos, $logtimestamps];
}
}
9 changes: 5 additions & 4 deletions mod/bigbluebuttonbn/lang/en/bigbluebuttonbn.php
Expand Up @@ -123,8 +123,8 @@
$string['completionvalidatestatetriggered'] = 'Validate completion has been triggered.';

$string['completionview'] = 'Require view';
$string['completionview_desc'] = 'Student must join a room or play a recording to complete it.';
$string['completionview_event_desc'] = 'Has joined the room or played a recording {$a} time(s)';
$string['completionview_desc'] = 'Student must view the Room to complete it.';
$string['completionview_event_desc'] = 'Has viewed the Room page.';
$string['sendnotification'] = 'Send notification';

$string['minute'] = 'minute';
Expand Down Expand Up @@ -378,8 +378,9 @@
$string['mod_form_field_hideuserlist'] = 'Hide user list';
$string['mod_form_field_lockonjoin'] = 'Lock settings on join';
$string['mod_form_locksettings'] = 'Lock settings';


$string['report_join_info'] = 'Has joined the room {$a} time(s)';
$string['report_play_recording_info'] = 'Has played a recording {$a} time(s)';
$string['report_room_view'] = 'Has viewed the Room page';
$string['starts_at'] = 'Starts';
$string['started_at'] = 'Started';
$string['ends_at'] = 'Ends';
Expand Down
31 changes: 7 additions & 24 deletions mod/bigbluebuttonbn/lib.php
Expand Up @@ -211,24 +211,11 @@ function bigbluebuttonbn_delete_instance($id) {
* @return stdClass with info and time (timestamp of the last log)
*/
function bigbluebuttonbn_user_outline(stdClass $course, stdClass $user, cm_info $mod, stdClass $bigbluebuttonbn): stdClass {
$customcompletion = new custom_completion($mod, $user->id);
$completed = $customcompletion->get_overall_completion_state();
$result = new stdClass();
if ($completed) {
$results = [];
$lastlog = 0;
foreach ($customcompletion->get_available_custom_rules() as $rule) {
$results[] = $customcompletion->get_printable_state($rule);
$lastlogrule = $customcompletion->get_last_log_timestamp($rule);
if ($lastlogrule > $lastlog) {
$lastlog = $lastlogrule;
}
}
$result = new stdClass();
$result->info = join(', ', $results);
$result->time = $lastlog;
}
return $result;
[$infos, $logtimestamps] = \mod_bigbluebuttonbn\local\helpers\user_info::get_user_info_outline($course, $user, $mod);
return (object) [
'info' => join(',', $infos),
'time' => !empty($logtimestamps) ? max($logtimestamps) : 0
];
}

/**
Expand All @@ -242,12 +229,8 @@ function bigbluebuttonbn_user_outline(stdClass $course, stdClass $user, cm_info
*
*/
function bigbluebuttonbn_user_complete(stdClass $course, stdClass $user, cm_info $mod, stdClass $bigbluebuttonbn) {
$customcompletion = new custom_completion($mod, $user->id);
$result = [];
foreach ($customcompletion->get_available_custom_rules() as $rule) {
$result[] = $customcompletion->get_printable_state($rule);
}
echo join(', ', $result);
[$infos] = \mod_bigbluebuttonbn\local\helpers\user_info::get_user_info_outline($course, $user, $mod);
echo join(', ', $infos);
}

/**
Expand Down
5 changes: 3 additions & 2 deletions mod/bigbluebuttonbn/tests/completion_test.php
Expand Up @@ -54,7 +54,7 @@ public function test_get_completion_state_no_rules() {
$completion = new custom_completion($bbactivitycm, $user->id);
$result = $completion->get_overall_completion_state();
// No custom rules so complete by default.
$this->assertEquals(COMPLETION_INCOMPLETE, $result);
$this->assertEquals(COMPLETION_COMPLETE, $result);
}

/**
Expand Down Expand Up @@ -213,6 +213,7 @@ public function test_view() {
$completion = new completion_info($this->get_course());
$completiondata = $completion->get_data($bbactivitycm);
$this->assertEquals(1, $completiondata->viewed);
$this->assertEquals(COMPLETION_INCOMPLETE, $completiondata->completionstate);
// A view means COMPLETE.
$this->assertEquals(COMPLETION_COMPLETE, $completiondata->completionstate);
}
}
24 changes: 9 additions & 15 deletions mod/bigbluebuttonbn/tests/lib_test.php
Expand Up @@ -112,18 +112,14 @@ public function test_bigbluebuttonbn_user_outline() {
$user = $generator->create_user();
$this->setUser($user);

list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();

list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance($this->get_course(),
['completion' => 2, 'completionview' => 1]);
$result = bigbluebuttonbn_user_outline($this->get_course(), $user, $bbactivitycm, $bbactivity);
$this->assertEquals((object) [], $result);

// Now create a couple of logs.
$instance = instance::get_from_instanceid($bbactivity->id);
logger::log_meeting_joined_event($instance, 0);
logger::log_recording_played_event($instance, 1);
$this->assertEquals((object) ['info' => '', 'time' => 0], $result);

bigbluebuttonbn_view($bbactivity, $this->get_course(), $bbactivitycm, $bbactivitycontext);
$result = bigbluebuttonbn_user_outline($this->get_course(), $user, $bbactivitycm, $bbactivity);
$this->assertStringContainsString(get_string('completionview_event_desc', 'mod_bigbluebuttonbn', 2), $result->info);
$this->assertStringContainsString(get_string('report_room_view', 'mod_bigbluebuttonbn'), $result->info);
}

/**
Expand All @@ -137,19 +133,17 @@ public function test_bigbluebuttonbn_user_complete() {

$generator = $this->getDataGenerator();
$user = $generator->create_and_enrol($this->get_course());
list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance($this->get_course(),
['completion' => 2, 'completionview' => 1]);
$this->setUser($user);

// Now create a couple of logs.
$instance = instance::get_from_instanceid($bbactivity->id);
$recordings = $this->create_recordings_for_instance($instance, [['name' => "Pre-Recording 1"]]);
logger::log_meeting_joined_event($instance, 0);
logger::log_recording_played_event($instance, $recordings[0]->id);
bigbluebuttonbn_view($bbactivity, $this->get_course(), $bbactivitycm, $bbactivitycontext);
ob_start();
bigbluebuttonbn_user_complete($this->get_course(), $user, $bbactivitycm, $bbactivity);
$output = ob_get_contents();
ob_end_clean();
$this->assertStringContainsString(get_string('completionview_event_desc', 'mod_bigbluebuttonbn', 2), $output);
$this->assertStringContainsString(get_string('report_room_view', 'mod_bigbluebuttonbn'), $output);
}

/**
Expand Down
85 changes: 85 additions & 0 deletions mod/bigbluebuttonbn/tests/local/helpers/user_info_test.php
@@ -0,0 +1,85 @@
<?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/>.
namespace mod_bigbluebuttonbn\local\helpers;

use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\logger;
use mod_bigbluebuttonbn\test\testcase_helper_trait;

/**
* User information printing test
*
* @package mod_bigbluebuttonbn
* @copyright 2022 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent@call-learning.fr)
* @covers \mod_bigbluebuttonbn\local\helpers\user_info
* @coversDefaultClass \mod_bigbluebuttonbn\local\helpers\user_info
*/
class user_info_test extends \advanced_testcase {
use testcase_helper_trait;

/**
* Test user info outline
*
* @return void
*/
public function test_get_user_info_outline() {
$this->initialise_mock_server();
$this->resetAfterTest();

$generator = $this->getDataGenerator();
$user = $generator->create_and_enrol($this->get_course());
list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
$this->setUser($user);

// Now create a couple of logs.
$instance = instance::get_from_instanceid($bbactivity->id);
$recordings = $this->create_recordings_for_instance($instance, [['name' => "Pre-Recording 1"]]);
logger::log_meeting_joined_event($instance, 0);
logger::log_recording_played_event($instance, $recordings[0]->id);
[$logjoins, $logtimes] = user_info::get_user_info_outline($this->get_course(), $user, $bbactivitycm);
$this->assertEquals([
'Has joined the room 1 time(s)',
'Has played a recording 1 time(s)'
], $logjoins);
$this->assertCount(2, $logtimes);
}
/**
* Test user info outline with several logs
*
* @return void
*/
public function test_get_user_info_outline_several_logs() {
$this->resetAfterTest();

$generator = $this->getDataGenerator();
$user = $generator->create_and_enrol($this->get_course());
list($bbactivitycontext, $bbactivitycm, $bbactivity) = $this->create_instance();
$this->setUser($user);

// Now create a couple of logs.
$instance = instance::get_from_instanceid($bbactivity->id);
logger::log_meeting_joined_event($instance, 0);
logger::log_meeting_joined_event($instance, 0);

[$logjoins, $logtimes] = user_info::get_user_info_outline($this->get_course(), $user, $bbactivitycm);
$this->assertEquals([
'Has joined the room 2 time(s)',
], $logjoins);
$this->assertCount(1, $logtimes);
}
}

0 comments on commit d9a62c9

Please sign in to comment.