Skip to content

Commit

Permalink
Mdl 79991 401 (#1)
Browse files Browse the repository at this point in the history
* MDL-76551 mod_bigbluebuttonbn: Refactor join url

* get_join url should not have as many parameters as they can be deduced from the instance.
* Refactoring it will allow to pass on more implicit parameters like the user profile file.

* MDL-76710 mod_bigbluebuttonbn: Subplugin implementation

    * Setup the base for extension type of plugins
    * Add basic unit test for extension plugin (callback and classes)

* MDL-76710 mod_bigbluebuttonbn: Action URL addons subplugin

    * Add action URL extension point

* MDL-78062 mod_bigblubuttonbn: Add backup for subplugin

* MDL-78907 mod_bigbluebuttonbn: Refactor instance class

* Make the constructor private as it should only be instancied through
static methods
* Do not duplicate the code between get_from_instanceid,
get_from_cmid and get_all_instances_in_course

* MDL-78907 mod_bigbluebuttonbn: Get cm when necessary

* The constructor of mod_bigbluebuttonbn\instance was provided with a cm_info.
This forced us to retrieve it whenever we created an instance. The issue is that
sometimes we need all the "other" data but not necessarily the cm_info.
So we now lazy load it.

* MDL-78907 mod_bigbluebuttonbn: Use the correct parameter type for id

* MDL-77545 mod_bigbluebuttonbn: Refactor get_instances_implementing

* We need a way to either have the classes implementing an interface/abstract
class or create instances.

* MDL-77545 mod_bigbluebuttonbn: Add form extension

* Add a new way to extend the BigBlueButtonBN form via subplugins
* Allow subplugins to extends information via new tables and use it in
the edit form.
* Add a new cache helping with potential perfomance issues introduced
by recurring calls to find out about associated tables in subplugins.

* MDL-78960 mod_bigbluebuttonbn: Add instanceid as action parameter

* In the bigbluebutton_proxy::action_url call to submodules, we need a way to get
the instance this is called upon so we can have information (parameters) for
this instance settings (like the new settings introduced by subplugins).
* Add the optional instanceid parameter in join/create/getMeetingInfo calls

* MDL-79255 mod_bigbluebuttonbn: Allow subplugins to be uninstalled

* Allow subplugins to be uninstalled

* fixup! MDL-77545 mod_bigbluebuttonbn: Add form extension

* MDL-79991 mod_bigbluebuttonbn: Fix code checker related issues

* Made a separate commit so to be able to port it again to master.

---------

Co-authored-by: Huong Nguyen <[email protected]>
  • Loading branch information
2 people authored and jfederico committed Apr 3, 2024
1 parent 5efbd6e commit 312015a
Show file tree
Hide file tree
Showing 39 changed files with 2,459 additions and 175 deletions.
43 changes: 43 additions & 0 deletions mod/bigbluebuttonbn/adminmanageplugins.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?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/>.

/**
* Allows the admin to manage extension plugins
*
* @copyright 2023 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David ([email protected])
*/

use mod_bigbluebuttonbn\local\plugins\admin_plugin_manager;

require_once(__DIR__ . '/../../config.php');
global $PAGE;
require_login();
$action = optional_param('action', null, PARAM_PLUGIN);
$plugin = optional_param('plugin', null, PARAM_PLUGIN);

if (!empty($plugin)) {
require_sesskey();
}

// Create the class for this controller.
$pluginmanager = new admin_plugin_manager();

$PAGE->set_context(context_system::instance());

// Execute the controller.
$pluginmanager->execute($action, $plugin);
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ protected function define_structure() {
// Define file annotations.
$bigbluebuttonbn->annotate_files('mod_bigbluebuttonbn', 'intro', null);

$this->add_subplugin_structure('bbbext', $bigbluebuttonbn, true);
// Return the root element (bigbluebuttonbn), wrapped into standard activity structure.
return $this->prepare_activity_structure($bigbluebuttonbn);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ class restore_bigbluebuttonbn_activity_structure_step extends restore_activity_s
*/
protected function define_structure() {
$paths = [];
$paths[] = new restore_path_element('bigbluebuttonbn', '/activity/bigbluebuttonbn');
$bbb = new restore_path_element('bigbluebuttonbn', '/activity/bigbluebuttonbn');
$paths[] = $bbb;
$paths[] = new restore_path_element('bigbluebuttonbn_logs', '/activity/bigbluebuttonbn/logs/log');
$paths[] = new restore_path_element('bigbluebuttonbn_recordings', '/activity/bigbluebuttonbn/recordings/recording');
$this->add_subplugin_structure('bbbext', $bbb);
// Return the paths wrapped into standard activity structure.
return $this->prepare_activity_structure($paths);
}
Expand Down
195 changes: 195 additions & 0 deletions mod/bigbluebuttonbn/classes/extension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<?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;

use cache;
use mod_bigbluebuttonbn\local\extension\action_url_addons;
use mod_bigbluebuttonbn\local\extension\mod_form_addons;
use mod_bigbluebuttonbn\local\extension\mod_instance_helper;
use stdClass;
use core_plugin_manager;

/**
* Generic subplugin management helper
*
* @package mod_bigbluebuttonbn
* @copyright 2023 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David ([email protected])
*/
class extension {
/**
* Plugin name for extension
*/
const BBB_EXTENSION_PLUGIN_NAME = 'bbbext';

/**
* Invoke a subplugin hook that will return additional parameters
*
* @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 = [],
?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, $instanceid);
$additionaldata = array_merge($additionaldata, $newdata ?? []);
$additionalmetadata = array_merge($additionalmetadata, $newmetadata ?? []);
}
return [
'data' => $additionaldata,
'metadata' => $additionalmetadata,
];
}

/**
* 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
*
* @param \MoodleQuickForm $mform
* @param stdClass|null $bigbluebuttondata
* @return array of custom completion addon classes instances
*/
public static function mod_form_addons_instances(\MoodleQuickForm $mform, ?stdClass $bigbluebuttondata = null): array {
return self::get_instances_implementing(mod_form_addons::class, [$mform, $bigbluebuttondata]);
}

/**
* Get additional join tables for instance when extension activated
*
* @return array of additional tables names. They all have a field called bigbluebuttonbnid that identifies the bbb instance.
*/
public static function get_join_tables(): array {
global $DB;
// We use cache here as it will be called very often.
$cache = cache::make('mod_bigbluebuttonbn', 'subplugins');
if ($cache->get('additionaltables')) {
return $cache->get('additionaltables');
}
$additionaltablesclasses = self::get_instances_implementing(mod_instance_helper::class);
$tables = [];
foreach ($additionaltablesclasses as $tableclass) {
$tables = array_merge($tables, $tableclass->get_join_tables() ?? []);
}
// Warning and removal for tables that do not have the bigbluebuttonid field.
foreach ($tables as $index => $table) {
$columns = $DB->get_columns($table);
if (empty($columns['bigbluebuttonbnid'])) {
debugging("get_instance_additional_tables: $table should have a column named bigbluebuttonid");
unset($tables[$index]);
}
}
$cache->set('additionaltables', $tables);
return $tables;
}

/**
* Add instance processing
*
* @param stdClass $data data to persist
* @return void
*/
public static function add_instance(stdClass $data): void {
$formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
foreach ($formmanagersclasses as $fmclass) {
$fmclass->add_instance($data);
}
}

/**
* Update instance processing
*
* @param stdClass $data data to persist
* @return void
*/
public static function update_instance(stdClass $data): void {
$formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
foreach ($formmanagersclasses as $fmclass) {
$fmclass->update_instance($data);
}
}

/**
* Delete instance processing
*
* @param int $id instance id
* @return void
*/
public static function delete_instance(int $id): void {
$formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
foreach ($formmanagersclasses as $fmclass) {
$fmclass->delete_instance($id);
}
}
}
Loading

0 comments on commit 312015a

Please sign in to comment.