Skip to content

Commit

Permalink
Merge branch 'MDL-78960-master' of https://github.com/call-learning/m…
Browse files Browse the repository at this point in the history
  • Loading branch information
snake committed Sep 12, 2023
2 parents 73c8675 + 6729c4b commit d372dba
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 75 deletions.
102 changes: 54 additions & 48 deletions mod/bigbluebuttonbn/classes/extension.php
Expand Up @@ -42,17 +42,23 @@ class extension {
* @param string $action
* @param array $data
* @param array $metadata
* @param int|null $instanceid
* @return array associative array with the additional data and metadata (indexed by 'data' and
* 'metadata' keys).
*/
public static function action_url_addons(string $action = '', array $data = [], array $metadata = []): array {
public static function action_url_addons(
string $action = '',
array $data = [],
array $metadata = [],
?int $instanceid = null
): array {
$allmutationclass = self::get_instances_implementing(action_url_addons::class);
$additionaldata = [];
$additionalmetadata = [];
foreach ($allmutationclass as $mutationclass) {
// Here we intentionally just pass data and metadata and not the result as we
// do not want subplugin to assume that another subplugin is doing a modification.
['data' => $newdata, 'metadata' => $newmetadata] = $mutationclass->execute($action, $data, $metadata);
['data' => $newdata, 'metadata' => $newmetadata] = $mutationclass->execute($action, $data, $metadata, $instanceid);
$additionaldata = array_merge($additionaldata, $newdata ?? []);
$additionalmetadata = array_merge($additionalmetadata, $newmetadata ?? []);
}
Expand All @@ -62,6 +68,52 @@ public static function action_url_addons(string $action = '', array $data = [],
];
}

/**
* Get new instance of classes that are named on the base of this classname and implementing this class
*
* @param string $classname
* @param array|null $newparameters additional parameters for the constructor.
* @return array
*/
protected static function get_instances_implementing(string $classname, ?array $newparameters = []): array {
$classes = self::get_classes_implementing($classname);
sort($classes); // Make sure all extension classes are returned in the same order. This is arbitrarily in
// alphabetical order and depends on the classname but this one way to ensure consistency across calls.
return array_map(function($targetclassname) use ($newparameters) {
// If $newparameters is null, the constructor will be called without parameters.
return new $targetclassname(...$newparameters);
}, $classes);
}

/**
* Get classes are named on the base of this classname and implementing this class
*
* @param string $classname
* @return array
*/
protected static function get_classes_implementing(string $classname): array {
// Get the class basename without Reflection API.
$classnamecomponents = explode("\\", $classname);
$classbasename = end($classnamecomponents);
$allsubs = core_plugin_manager::instance()->get_plugins_of_type(self::BBB_EXTENSION_PLUGIN_NAME);
$extensionclasses = [];
foreach ($allsubs as $sub) {
if (!$sub->is_enabled()) {
continue;
}
$targetclassname = "\\bbbext_{$sub->name}\\bigbluebuttonbn\\$classbasename";
if (!class_exists($targetclassname)) {
continue;
}
if (!is_subclass_of($targetclassname, $classname)) {
debugging("The class $targetclassname should extend $classname in the subplugin {$sub->name}. Ignoring.");
continue;
}
$extensionclasses[] = $targetclassname;
}
return $extensionclasses;
}

/**
* Get all mod_form addons classes instances
*
Expand Down Expand Up @@ -142,50 +194,4 @@ public static function delete_instance(int $id): void {
$fmclass->delete_instance($id);
}
}

/**
* Get new instance of classes that are named on the base of this classname and implementing this class
*
* @param string $classname
* @param array|null $newparameters additional parameters for the constructor.
* @return array
*/
protected static function get_instances_implementing(string $classname, ?array $newparameters = []): array {
$classes = self::get_classes_implementing($classname);
sort($classes); // Make sure all extension classes are returned in the same order. This is arbitrarily in
// alphabetical order and depends on the classname but this one way to ensure consistency across calls.
return array_map(function($targetclassname) use ($newparameters) {
// If $newparameters is null, the constructor will be called without parameters.
return new $targetclassname(...$newparameters);
}, $classes);
}

/**
* Get classes are named on the base of this classname and implementing this class
*
* @param string $classname
* @return array
*/
protected static function get_classes_implementing(string $classname): array {
// Get the class basename without Reflection API.
$classnamecomponents = explode("\\", $classname);
$classbasename = end($classnamecomponents);
$allsubs = core_plugin_manager::instance()->get_plugins_of_type(self::BBB_EXTENSION_PLUGIN_NAME);
$extensionclasses = [];
foreach ($allsubs as $sub) {
if (!$sub->is_enabled()) {
continue;
}
$targetclassname = "\\bbbext_{$sub->name}\\bigbluebuttonbn\\$classbasename";
if (!class_exists($targetclassname)) {
continue;
}
if (!is_subclass_of($targetclassname, $classname)) {
debugging("The class $targetclassname should extend $classname in the subplugin {$sub->name}. Ignoring.");
continue;
}
$extensionclasses[] = $targetclassname;
}
return $extensionclasses;
}
}
18 changes: 11 additions & 7 deletions mod/bigbluebuttonbn/classes/local/proxy/bigbluebutton_proxy.php
Expand Up @@ -125,7 +125,7 @@ private static function internal_get_join_url(
$data['avatarURL'] = self::get_avatar_url($user)->out(false);
}
}
return self::action_url('join', $data);
return self::action_url('join', $data, [], $instance->get_instance_id());
}

/**
Expand Down Expand Up @@ -464,16 +464,18 @@ public static function get_server_not_available_url(instance $instance): string
* @param array $metadata
* @param string|null $presentationname
* @param string|null $presentationurl
* @param int|null $instanceid
* @return array
* @throws bigbluebutton_exception
*/
public static function create_meeting(
array $data,
array $metadata,
?string $presentationname = null,
?string $presentationurl = null
?string $presentationurl = null,
?int $instanceid = null
): array {
$createmeetingurl = self::action_url('create', $data, $metadata);
$createmeetingurl = self::action_url('create', $data, $metadata, $instanceid);

$curl = new curl();
if (!is_null($presentationname) && !is_null($presentationurl)) {
Expand Down Expand Up @@ -507,10 +509,11 @@ public static function create_meeting(
* Get meeting info for a given meeting id
*
* @param string $meetingid
* @param int|null $instanceid
* @return array
*/
public static function get_meeting_info(string $meetingid): array {
$xmlinfo = self::fetch_endpoint_xml('getMeetingInfo', ['meetingID' => $meetingid]);
public static function get_meeting_info(string $meetingid, ?int $instanceid = null): array {
$xmlinfo = self::fetch_endpoint_xml('getMeetingInfo', ['meetingID' => $meetingid], [], $instanceid);
self::assert_returned_xml($xmlinfo, ['meetingid' => $meetingid]);
return (array) $xmlinfo;
}
Expand All @@ -520,9 +523,10 @@ public static function get_meeting_info(string $meetingid): array {
*
* @param string $meetingid
* @param string $modpw
* @param int|null $instanceid
*/
public static function end_meeting(string $meetingid, string $modpw): void {
$xml = self::fetch_endpoint_xml('end', ['meetingID' => $meetingid, 'password' => $modpw]);
public static function end_meeting(string $meetingid, string $modpw, ?int $instanceid = null): void {
$xml = self::fetch_endpoint_xml('end', ['meetingID' => $meetingid, 'password' => $modpw], [], $instanceid);
self::assert_returned_xml($xml, ['meetingid' => $meetingid]);
}

Expand Down
17 changes: 13 additions & 4 deletions mod/bigbluebuttonbn/classes/local/proxy/proxy_base.php
Expand Up @@ -52,11 +52,18 @@ abstract class proxy_base {
* @param string $action
* @param array $data
* @param array $metadata
* @param int|null $instanceid
* @return string
*/
protected static function action_url(string $action = '', array $data = [], array $metadata = []): string {
protected static function action_url(
string $action = '',
array $data = [],
array $metadata = [],
?int $instanceid = null
): string {
$baseurl = self::sanitized_url() . $action . '?';
['data' => $additionaldata, 'metadata' => $additionalmetadata] = extension::action_url_addons($action, $data, $metadata);
['data' => $additionaldata, 'metadata' => $additionalmetadata] =
extension::action_url_addons($action, $data, $metadata, $instanceid);
$data = array_merge($data, $additionaldata ?? []);
$metadata = array_merge($metadata, $additionalmetadata ?? []);

Expand Down Expand Up @@ -168,20 +175,22 @@ private static function is_known_server_unavailable_errorcode(string $messagekey
* @param string $action
* @param array $data
* @param array $metadata
* @param int|null $instanceid
* @return null|bool|\SimpleXMLElement
*/
protected static function fetch_endpoint_xml(
string $action,
array $data = [],
array $metadata = []
array $metadata = [],
?int $instanceid = null
) {
if (PHPUNIT_TEST && !defined('TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER')) {
return true; // In case we still use fetch and mock server is not defined, this prevents
// an error. This can happen if a function from lib.php is called in test from other modules
// for example.
}
$curl = new curl();
return $curl->get(self::action_url($action, $data, $metadata));
return $curl->get(self::action_url($action, $data, $metadata, $instanceid));
}

/**
Expand Down
Expand Up @@ -49,7 +49,7 @@ protected static function invalidate_cache_for_recording(string $recordid): void
* @param string $recordid a recording id
* @return bool
*/
public static function delete_recording(string $recordid): bool {
public static function delete_recording(string $recordid, ?int $instanceid = null): bool {
$result = self::fetch_endpoint_xml('deleteRecordings', ['recordID' => $recordid]);
if (!$result || $result->returncode != 'SUCCESS') {
return false;
Expand Down
21 changes: 16 additions & 5 deletions mod/bigbluebuttonbn/classes/meeting.php
Expand Up @@ -166,7 +166,13 @@ public function create_meeting() {
$presentation = $this->instance->get_presentation_for_bigbluebutton_upload(); // The URL must contain nonce.
$presentationname = $presentation['name'] ?? null;
$presentationurl = $presentation['url'] ?? null;
$response = bigbluebutton_proxy::create_meeting($data, $metadata, $presentationname, $presentationurl);
$response = bigbluebutton_proxy::create_meeting(
$data,
$metadata,
$presentationname,
$presentationurl,
$this->instance->get_instance_id()
);
// New recording management: Insert a recordingID that corresponds to the meeting created.
if ($this->instance->is_recorded()) {
$recording = new recording(0, (object) [
Expand All @@ -184,7 +190,11 @@ public function create_meeting() {
* Send an end meeting message to BBB server
*/
public function end_meeting() {
bigbluebutton_proxy::end_meeting($this->instance->get_meeting_id(), $this->instance->get_moderator_password());
bigbluebutton_proxy::end_meeting(
$this->instance->get_meeting_id(),
$this->instance->get_moderator_password(),
$this->instance->get_instance_id()
);
}

/**
Expand Down Expand Up @@ -240,7 +250,7 @@ protected function do_get_meeting_info(bool $updatecache = false): stdClass {
$meetinginfo->statusrunning = false;
$meetinginfo->createtime = null;

$info = self::retrieve_cached_meeting_info($this->instance->get_meeting_id(), $updatecache);
$info = self::retrieve_cached_meeting_info($this->instance, $updatecache);
if (!empty($info)) {
$meetinginfo->statusrunning = $info['running'] === 'true';
$meetinginfo->createtime = $info['createTime'] ?? null;
Expand Down Expand Up @@ -322,12 +332,13 @@ protected function get_status_message(object $meetinginfo, instance $instance):
/**
* Gets a meeting info object cached or fetched from the live session.
*
* @param string $meetingid
* @param instance $instance
* @param bool $updatecache
*
* @return array
*/
protected static function retrieve_cached_meeting_info($meetingid, $updatecache = false) {
protected static function retrieve_cached_meeting_info(instance $instance, $updatecache = false) {
$meetingid = $instance->get_meeting_id();
$cachettl = (int) config::get('waitformoderator_cache_ttl');
$cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'mod_bigbluebuttonbn', 'meetings_cache');
$result = $cache->get($meetingid);
Expand Down
Expand Up @@ -31,13 +31,28 @@ class action_url_addons extends \mod_bigbluebuttonbn\local\extension\action_url_
* @param string $action
* @param array $data
* @param array $metadata
* @param int|null $instanceid
* @return array associative array with the additional data and metadata (indexed by 'data' and
* 'metadata' keys)
*/
public function execute(string $action = '', array $data = [], array $metadata = []): array {
public function execute(
string $action = '',
array $data = [],
array $metadata = [],
?int $instanceid = null
): array {
if ($action == 'create' || $action == 'join') {
global $DB;
$record = $DB->get_record('bbbext_simple', [
'bigbluebuttonbnid' => $instanceid,
]);
if ($record) {
$metadata['newfield'] = $record->newfield ?? '';
}
}
return [
'data' => $action == 'create' ? [] : ['a', 'b'],
'metadata' => in_array('Test', $metadata) ? ['c', 'd'] : []
'data' => $data,
'metadata' => $metadata,
];
}
}
Expand Up @@ -53,10 +53,10 @@ public function update_instance(stdClass $bigbluebuttonbn): void {
if (empty($record)) {
$record = new stdClass();
$record->bigbluebuttonbnid = $bigbluebuttonbn->id;
$record->newfield = $bigbluebuttonbn->newfield;
$record->newfield = $bigbluebuttonbn->newfield ?? '';
$DB->insert_record('bbbext_simple', $record);
} else {
$record->newfield = $bigbluebuttonbn->newfield;
$record->newfield = $bigbluebuttonbn->newfield ?? '';
$DB->update_record('bbbext_simple', $record);
}
}
Expand Down
35 changes: 30 additions & 5 deletions mod/bigbluebuttonbn/tests/local/extension_test.php
Expand Up @@ -18,7 +18,9 @@
use backup;
use backup_controller;
use mod_bigbluebuttonbn\extension;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\extension\mod_instance_helper;
use mod_bigbluebuttonbn\meeting;
use mod_bigbluebuttonbn\test\subplugins_test_helper_trait;
use mod_bigbluebuttonbn\test\testcase_helper_trait;
use restore_controller;
Expand Down Expand Up @@ -152,17 +154,40 @@ public function test_mod_instance_helper_delete() {
public function test_action_url_addons() {
// Enable plugin.
$this->enable_plugins(true);
// Set a random var here.
$var1 = [];
$var2 = ['Test'];
['data' => $additionalvar1, 'metadata' => $additionalvar2] = extension::action_url_addons('create', [], ['Test']);
$course = $this->get_course();
[$cm, $cminfo, $bbactivity] = $this->create_instance($course);
$bbactivity->newfield = 4;
extension::update_instance($bbactivity);
['data' => $additionalvar1, 'metadata' => $additionalvar2] =
extension::action_url_addons('create', [], ['bbb-meta' => 'Test'], $bbactivity->id);
$this->assertEmpty($additionalvar1);
$this->assertCount(2, $additionalvar2);
$this->assertEquals($additionalvar2['newfield'], 4);
['data' => $additionalvar1, 'metadata' => $additionalvar2] = extension::action_url_addons('delete');
$this->assertNotEmpty($additionalvar1);
$this->assertEmpty($additionalvar1);
$this->assertEmpty($additionalvar2);
}

/**
* Test the action_url_addons with plugin enabled
*
* @return void
* @covers \mod_bigbluebuttonbn\extension::action_url_addons
*/
public function test_join_url_with_additional_field() {
$this->initialise_mock_server();
// Enable plugin.
$this->enable_plugins(true);
$course = $this->get_course();
[$cm, $cminfo, $bbactivity] = $this->create_instance($course);
$bbactivity->newfield = 4;
extension::update_instance($bbactivity);
$instance = instance::get_from_instanceid($bbactivity->id);
$meeting = new meeting($instance);
$meetingjoinurl = $meeting->get_join_url();
$this->assertStringContainsString('newfield=4', $meetingjoinurl);
}

/**
* Test backup restore (with extension)
*
Expand Down

0 comments on commit d372dba

Please sign in to comment.