mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 16:36:37 +02:00
MDL-73308 mod_bigbluebuttonn: Breakout room
* Fetch recording attached to breakout meetings * Add tests for breakoutrooms
This commit is contained in:
parent
d24a4ab56f
commit
628ee05f98
7 changed files with 210 additions and 33 deletions
|
@ -223,20 +223,20 @@ class recording_proxy extends proxy_base {
|
|||
}
|
||||
|
||||
$recordings = [];
|
||||
// If there were meetings already created.
|
||||
// If there were recordings already created.
|
||||
foreach ($xml->recordings->recording as $recordingxml) {
|
||||
$recording = self::parse_recording($recordingxml);
|
||||
$recordings[$recording['recordID']] = $recording;
|
||||
|
||||
// Check if there is childs.
|
||||
// Check if there are any child.
|
||||
if (isset($recordingxml->breakoutRooms->breakoutRoom)) {
|
||||
$breakoutrooms = [];
|
||||
foreach ($recordingxml->breakoutRooms->breakoutRoom as $breakoutroom) {
|
||||
$xml = self::fetch_endpoint_xml('getRecordings', ['recordID' => implode(',', (array) $breakoutroom)]);
|
||||
if (!$xml || $xml->returncode != 'SUCCESS' || empty($xml->recordings)) {
|
||||
continue;
|
||||
$breakoutrooms[] = trim((string) $breakoutroom);
|
||||
}
|
||||
|
||||
// If there were meetings already created.
|
||||
if ($breakoutrooms) {
|
||||
$xml = self::fetch_endpoint_xml('getRecordings', ['recordID' => implode(',', $breakoutrooms)]);
|
||||
if ($xml && $xml->returncode == 'SUCCESS' && isset($xml->recordings)) {
|
||||
// If there were already created meetings.
|
||||
foreach ($xml->recordings->recording as $subrecordingxml) {
|
||||
$recording = self::parse_recording($subrecordingxml);
|
||||
$recordings[$recording['recordID']] = $recording;
|
||||
|
@ -244,6 +244,7 @@ class recording_proxy extends proxy_base {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $recordings;
|
||||
}
|
||||
|
|
|
@ -117,8 +117,6 @@ class recording extends persistent {
|
|||
bool $includeimported = false,
|
||||
bool $onlyimported = false
|
||||
): array {
|
||||
global $DB;
|
||||
|
||||
[$selects, $params] = self::get_basic_select_from_parameters(false, $includeimported, $onlyimported);
|
||||
$selects[] = "bigbluebuttonbnid = :bbbid";
|
||||
$params['bbbid'] = $instance->get_instance_id();
|
||||
|
@ -802,12 +800,37 @@ class recording extends persistent {
|
|||
|
||||
$foundcount = 0;
|
||||
foreach ($metadatas as $recordingid => $metadata) {
|
||||
mtrace("==> Found updated metadata for {$recordingid}. Updating local cache.");
|
||||
mtrace("==> Found metadata for {$recordingid}.");
|
||||
$id = array_search($recordingid, $recordingids);
|
||||
|
||||
if (!$id) {
|
||||
// Recording was not found, skip.
|
||||
mtrace("===> Skip as fetched recording was not found.");
|
||||
continue;
|
||||
}
|
||||
// Recording was found, update status.
|
||||
mtrace("===> Update local cache as fetched recording was found.");
|
||||
$recording = new self(0, $recordings[$id], $metadata);
|
||||
$recording->set_status(self::RECORDING_STATUS_PROCESSED);
|
||||
$foundcount++;
|
||||
|
||||
// Iterate breakout recordings (if any) and update status.
|
||||
foreach ($metadata['breakouts'] as $breakoutrecordingid => $breakoutmetadata) {
|
||||
$breakoutrecording = self::get_record(['recordingid' => $breakoutrecordingid]);
|
||||
if (!$breakoutrecording) {
|
||||
$breakoutrecording = new recording(0,
|
||||
(object) [
|
||||
'courseid' => $recording->get('courseid'),
|
||||
'bigbluebuttonbnid' => $recording->get('bigbluebuttonbnid'),
|
||||
'groupid' => $recording->get('groupid'),
|
||||
'recordingid' => $breakoutrecordingid
|
||||
],
|
||||
$breakoutmetadata
|
||||
);
|
||||
$breakoutrecording->create();
|
||||
}
|
||||
$breakoutrecording->set_status(self::RECORDING_STATUS_PROCESSED);
|
||||
$foundcount++;
|
||||
}
|
||||
}
|
||||
|
||||
mtrace("=> Finished processing recordings. Updated status for {$foundcount} / {$recordingcount} recordings.");
|
||||
|
|
|
@ -160,17 +160,18 @@ trait testcase_helper_trait {
|
|||
* @return array
|
||||
* @throws \coding_exception
|
||||
*/
|
||||
protected function create_recordings_for_instance(instance $instance, array $recordingdata = []): array {
|
||||
protected function create_recordings_for_instance(instance $instance, array $recordingdata = [],
|
||||
$additionalmeetingdata = []): array {
|
||||
$recordings = [];
|
||||
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
|
||||
// Create the meetings on the mock server, so like this we can find the recordings.
|
||||
$meeting = new meeting($instance);
|
||||
if (!$meeting->is_running()) {
|
||||
$bbbgenerator->create_meeting([
|
||||
$additionalmeetingdata = array_merge([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id()
|
||||
|
||||
]);
|
||||
], $additionalmeetingdata);
|
||||
$bbbgenerator->create_meeting($additionalmeetingdata);
|
||||
}
|
||||
foreach ($recordingdata as $rindex => $data) {
|
||||
$recordings[] = $bbbgenerator->create_recording(
|
||||
|
|
|
@ -233,9 +233,8 @@ class mod_bigbluebuttonbn_generator extends \testing_module_generator {
|
|||
*/
|
||||
protected function create_mockserver_recording(instance $instance, stdClass $recordingdata, array $data): string {
|
||||
$mockdata = array_merge((array) $recordingdata, [
|
||||
'meetingID' => $instance->get_meeting_id(),
|
||||
'sequence' => 1,
|
||||
'meta' => [
|
||||
'isBreakout' => 'false',
|
||||
'bn-presenter-name' => $data['presentername'] ?? 'Fake presenter',
|
||||
'bn-recording-ready-url' => new moodle_url('/mod/bigbluebuttonbn/bbb_broker.php', [
|
||||
'action' => 'recording_ready',
|
||||
|
@ -246,6 +245,15 @@ class mod_bigbluebuttonbn_generator extends \testing_module_generator {
|
|||
'bbb-recording-tags' => $data['tags'] ?? '',
|
||||
],
|
||||
]);
|
||||
if (!empty($data['isBreakout'])) {
|
||||
// If it is a breakout meeting, we do not have any way to know the real Id of the meeting
|
||||
// unless we query the list of submeetings.
|
||||
// For now we will just send the parent ID and let the mock server deal with the sequence + parentID
|
||||
// to find the meetingID.
|
||||
$mockdata['parentMeetingID'] = $instance->get_meeting_id();
|
||||
} else {
|
||||
$mockdata['meetingID'] = $instance->get_meeting_id();
|
||||
}
|
||||
|
||||
$result = $this->send_mock_request('backoffice/createRecording', [], $mockdata);
|
||||
|
||||
|
@ -269,7 +277,6 @@ class mod_bigbluebuttonbn_generator extends \testing_module_generator {
|
|||
|
||||
// Default room configuration.
|
||||
$roomconfig = array_merge($data, [
|
||||
'meetingID' => $meetingid,
|
||||
'meetingName' => $instance->get_meeting_name(),
|
||||
'attendeePW' => $instance->get_viewer_password(),
|
||||
'moderatorPW' => $instance->get_moderator_password(),
|
||||
|
@ -285,6 +292,14 @@ class mod_bigbluebuttonbn_generator extends \testing_module_generator {
|
|||
'bbb-recording-name' => $instance->get_meeting_name(),
|
||||
],
|
||||
]);
|
||||
if (!empty($roomconfig['isBreakout'])) {
|
||||
// If it is a breakout meeting, we do not have any way to know the real Id of the meeting
|
||||
// For now we will just send the parent ID and let the mock server deal with the sequence + parentID
|
||||
// to find the meetingID.
|
||||
$roomconfig['parentMeetingID'] = $instance->get_meeting_id();
|
||||
} else {
|
||||
$roomconfig['meetingID'] = $meetingid;
|
||||
}
|
||||
|
||||
$this->send_mock_request('backoffice/createMeeting', [], $roomconfig);
|
||||
|
||||
|
|
|
@ -14,19 +14,10 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy provider tests.
|
||||
*
|
||||
* @package mod_bigbluebuttonbn
|
||||
* @copyright 2018 - present, Blindside Networks Inc
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @author Jesus Federico (jesus [at] blindsidenetworks [dt] com)
|
||||
*/
|
||||
|
||||
namespace mod_bigbluebuttonbn\local\bigbluebutton\recordings;
|
||||
|
||||
/**
|
||||
* Privacy provider tests class.
|
||||
* Recording data tests.
|
||||
*
|
||||
* @package mod_bigbluebuttonbn
|
||||
* @copyright 2018 - present, Blindside Networks Inc
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?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\proxy;
|
||||
|
||||
use mod_bigbluebuttonbn\instance;
|
||||
use mod_bigbluebuttonbn\test\testcase_helper_trait;
|
||||
|
||||
/**
|
||||
* Recording proxy tests class.
|
||||
*
|
||||
* @package mod_bigbluebuttonbn
|
||||
* @copyright 2018 - present, Blindside Networks Inc
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @author Jesus Federico (jesus [at] blindsidenetworks [dt] com)
|
||||
* @covers \mod_bigbluebuttonbn\local\proxy\recording_proxy
|
||||
* @coversDefaultClass \mod_bigbluebuttonbn\local\proxy\recording_proxy
|
||||
*/
|
||||
class recording_proxy_test extends \advanced_testcase {
|
||||
use testcase_helper_trait;
|
||||
|
||||
/**
|
||||
* Simple recording fetcher test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_fetch_recordings() {
|
||||
$this->resetAfterTest();
|
||||
$this->initialise_mock_server();
|
||||
[$context, $cm, $bbbactivity] = $this->create_instance();
|
||||
$instance = instance::get_from_instanceid($bbbactivity->id);
|
||||
$recordings = $this->create_recordings_for_instance($instance, [['name' => 'Recording 1'], ['name' => 'Recording 2']]);
|
||||
$recordingsid = array_map(function($r) {
|
||||
return $r->recordingid;
|
||||
}, $recordings);
|
||||
$recordings = recording_proxy::fetch_recordings($recordingsid);
|
||||
$this->assertCount(2, $recordings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple recording with breakoutroom fetcher test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_fetch_recordings_breakoutroom() {
|
||||
$this->resetAfterTest();
|
||||
$this->initialise_mock_server();
|
||||
[$context, $cm, $bbbactivity] = $this->create_instance();
|
||||
$instance = instance::get_from_instanceid($bbbactivity->id);
|
||||
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
|
||||
$mainmeeting = $bbbgenerator->create_meeting([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id(),
|
||||
]);
|
||||
// TODO: here we artificially create breakout meetings but the current implementations does not handle
|
||||
// breakout rooms for one BBB instance. At this point we just have the ability to retrieve subrecordings
|
||||
// from breakout rooms and manage them as if they belong to the parent recording.
|
||||
// The meetingId is not sent to the server but autogenerated by the mock server and
|
||||
// parentID is the meetingID from the current instance.
|
||||
$submeeting1 = $bbbgenerator->create_meeting([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id(),
|
||||
'isBreakout' => true,
|
||||
'sequence' => 1
|
||||
]);
|
||||
$submeeting2 = $bbbgenerator->create_meeting([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id(),
|
||||
'isBreakout' => true,
|
||||
'sequence' => 2
|
||||
]);
|
||||
$recordings = $this->create_recordings_for_instance($instance,
|
||||
[
|
||||
['name' => 'Recording 1'],
|
||||
['name' => 'Recording 2', 'isBreakout' => true, 'sequence' => 1],
|
||||
['name' => 'Recording 3', 'isBreakout' => true, 'sequence' => 2]
|
||||
]
|
||||
);
|
||||
$recordingsid = array_map(function($r) {
|
||||
return $r->recordingid;
|
||||
}, $recordings);
|
||||
$recordings = recording_proxy::fetch_recordings([$recordingsid[0]]);
|
||||
$this->assertCount(3, $recordings);
|
||||
}
|
||||
}
|
|
@ -253,4 +253,52 @@ class recording_test extends \advanced_testcase {
|
|||
}, $recordings);
|
||||
$this->assertContains($recordingname, $recordingnames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple recording with breakoutroom fetcher test
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_recordings_breakoutroom() {
|
||||
$this->resetAfterTest();
|
||||
$this->initialise_mock_server();
|
||||
[$context, $cm, $bbbactivity] = $this->create_instance();
|
||||
$instance = instance::get_from_instanceid($bbbactivity->id);
|
||||
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
|
||||
$mainmeeting = $bbbgenerator->create_meeting([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id(),
|
||||
]);
|
||||
// This creates a meeting to receive the recordings (specific to the mock server implementation). See recording_proxy_test.
|
||||
$bbbgenerator->create_meeting([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id(),
|
||||
'isBreakout' => true,
|
||||
'sequence' => 1
|
||||
]);
|
||||
$bbbgenerator->create_meeting([
|
||||
'instanceid' => $instance->get_instance_id(),
|
||||
'groupid' => $instance->get_group_id(),
|
||||
'isBreakout' => true,
|
||||
'sequence' => 2
|
||||
]);
|
||||
// For now only recording from the main room have been created.
|
||||
$this->create_recordings_for_instance($instance,
|
||||
[
|
||||
['name' => 'Recording 1'],
|
||||
]
|
||||
);
|
||||
$recordings = recording::get_recordings_for_instance($instance);
|
||||
$this->assertCount(1, $recordings);
|
||||
|
||||
// Now the breakoutroom recordings appears.
|
||||
$this->create_recordings_for_instance($instance,
|
||||
[
|
||||
['name' => 'Recording 2', 'isBreakout' => true, 'sequence' => 1],
|
||||
['name' => 'Recording 3', 'isBreakout' => true, 'sequence' => 2]
|
||||
]
|
||||
);
|
||||
$recordings = recording::get_recordings_for_instance($instance);
|
||||
$this->assertCount(3, $recordings);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue