diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..50e1da5
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,116 @@
+name: Moodle Plugin CI
+
+on: [push, pull_request]
+
+jobs:
+ test:
+ runs-on: ubuntu-22.04
+
+ services:
+ postgres:
+ image: postgres:13
+ env:
+ POSTGRES_USER: 'postgres'
+ POSTGRES_HOST_AUTH_METHOD: 'trust'
+ ports:
+ - 5432:5432
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3
+
+ mariadb:
+ image: mariadb:10
+ env:
+ MYSQL_USER: 'root'
+ MYSQL_ALLOW_EMPTY_PASSWORD: "true"
+ MYSQL_CHARACTER_SET_SERVER: "utf8mb4"
+ MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci"
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ['8.1']
+ moodle-branch: ['MOODLE_403_STABLE']
+ database: [pgsql, mariadb]
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v3
+ with:
+ path: plugin
+
+ - name: Setup PHP ${{ matrix.php }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: ${{ matrix.extensions }}
+ ini-values: max_input_vars=5000
+ # If you are not using code coverage, keep "none". Otherwise, use "pcov" (Moodle 3.10 and up) or "xdebug".
+ # If you try to use code coverage with "none", it will fallback to phpdbg (which has known problems).
+ coverage: none
+
+ - name: Initialise moodle-plugin-ci
+ run: |
+ composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4
+ echo $(cd ci/bin; pwd) >> $GITHUB_PATH
+ echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
+ sudo locale-gen en_AU.UTF-8
+ echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
+
+ - name: Install moodle-plugin-ci
+ run: |
+ moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
+ env:
+ DB: ${{ matrix.database }}
+ MOODLE_BRANCH: ${{ matrix.moodle-branch }}
+
+ - name: PHP Lint
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci phplint
+
+ - name: PHP Copy/Paste Detector
+ continue-on-error: true # This step will show errors but will not fail
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci phpcpd
+
+ - name: PHP Mess Detector
+ continue-on-error: true # This step will show errors but will not fail
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci phpmd
+
+ - name: Moodle Code Checker
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci phpcs --max-warnings 0
+
+ - name: Moodle PHPDoc Checker
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci phpdoc --max-warnings 0
+
+ - name: Validating
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci validate
+
+ - name: Check upgrade savepoints
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci savepoints
+
+ - name: Mustache Lint
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci mustache
+
+ - name: Grunt
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci grunt --max-lint-warnings 0
+
+ - name: PHPUnit tests
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci phpunit --fail-on-warning
+
+ - name: Behat features
+ if: ${{ !cancelled() }}
+ run: moodle-plugin-ci behat --profile chrome
+
+ - name: Mark cancelled jobs as failed.
+ if: ${{ cancelled() }}
+ run: exit 1
\ No newline at end of file
diff --git a/README.md b/README.md
index 86b2d43..5008c26 100644
--- a/README.md
+++ b/README.md
@@ -4,15 +4,16 @@ BigblueButton Extension - FlexURL
* Copyright: Blindside Networks Inc
* License: GNU GENERAL PUBLIC LICENSE Version 3
-This is an extension plugin for BigBluebButtonBN module that will allow you to some parameters dynamically
-to the create and join URL. This is sometimes needed for specific BigBlueButton integrations.
+This is an extension plugin for the BigBlueButtonBN module. This will allow user to add parameters to a create and join action url, so to
+be able to address a variety of use cases.
+For now the parameters are not "free forms" but fixed on entities like user, course and module so to be able to address the most common use cases while
+keeping some control on the parameters that are passed to the BigBlueButton server.
Description
===========
This plugin shows how to extend BigBluebButtonBN module to:
* Add a new parameter to an Action URL (create and join)
-* Setup a new parameter in the BigBlueButtonBN module settings (and edit form)
Installation
diff --git a/backup/moodle2/backup_bbbext_flexurl_subplugin.class.php b/backup/moodle2/backup_bbbext_flexurl_subplugin.class.php
index c729e2b..64a5404 100644
--- a/backup/moodle2/backup_bbbext_flexurl_subplugin.class.php
+++ b/backup/moodle2/backup_bbbext_flexurl_subplugin.class.php
@@ -33,17 +33,21 @@ protected function define_bigbluebuttonbn_subplugin_structure() {
// Create XML elements.
$subplugin = $this->get_subplugin_element();
$subpluginwrapper = new backup_nested_element($this->get_recommended_name());
- $subpluginelement = new backup_nested_element('bbbext_flexurl',
+ $subpluginelement = new backup_nested_element(
+ 'bbbext_flexurl',
null,
- ['additionalparams']);
+ ['eventtype', 'paramname', 'paramvalue']
+ );
// Connect XML elements into the tree.
$subplugin->add_child($subpluginwrapper);
$subpluginwrapper->add_child($subpluginelement);
// Set source to populate the data.
- $subpluginelement->set_source_table('bbbext_flexurl',
- ['bigbluebuttonbnid' => backup::VAR_PARENTID]);
+ $subpluginelement->set_source_table(
+ 'bbbext_flexurl',
+ ['bigbluebuttonbnid' => backup::VAR_PARENTID]
+ );
return $subplugin;
}
diff --git a/backup/moodle2/restore_bbbext_flexurl_subplugin.class.php b/backup/moodle2/restore_bbbext_flexurl_subplugin.class.php
index 98d9b88..7155444 100644
--- a/backup/moodle2/restore_bbbext_flexurl_subplugin.class.php
+++ b/backup/moodle2/restore_bbbext_flexurl_subplugin.class.php
@@ -30,7 +30,6 @@ class restore_bbbext_flexurl_subplugin extends restore_subplugin {
* @return array
*/
protected function define_bigbluebuttonbn_subplugin_structure() {
-
$paths = [];
$elename = $this->get_namefor('bigbluebuttonbn');
@@ -38,7 +37,6 @@ protected function define_bigbluebuttonbn_subplugin_structure() {
$elepath = $this->get_pathfor('/bbbext_flexurl');
$paths[] = new restore_path_element($elename, $elepath);
-
return $paths;
}
diff --git a/classes/bigbluebuttonbn/action_url_addons.php b/classes/bigbluebuttonbn/action_url_addons.php
index 60f1b00..7851dc7 100644
--- a/classes/bigbluebuttonbn/action_url_addons.php
+++ b/classes/bigbluebuttonbn/action_url_addons.php
@@ -15,6 +15,10 @@
// along with Moodle. If not, see .
namespace bbbext_flexurl\bigbluebuttonbn;
+use bbbext_flexurl\utils;
+use core_form\util;
+use mod_bigbluebuttonbn\instance;
+
/**
* A single action class to mutate the action URL.
*
@@ -36,31 +40,23 @@ class action_url_addons extends \mod_bigbluebuttonbn\local\extension\action_url_
* 'metadata' keys)
*/
public function execute(string $action = '', array $data = [], array $metadata = [], ?int $instanceid = null): array {
- if ($action == 'create') {
- $analyticcburl = get_config('bbbext_flexurl', 'analytics_callback_url');
- if ($analyticcburl) {
- $metadata['analytics-callback-url'] = $analyticcburl;
- }
- }
- if ($action == 'create' || $action == 'join') {
- if (empty($instanceid)) {
- if (!(defined('PHPUNIT_TEST') && PHPUNIT_TEST) && !defined('BEHAT_SITE_RUNNING')) {
- // Debugging messages will fail mod_bigbluebuttonbn behat or phpunit tests as soon as the plugin is installed.
- // Which is not what we want here.
- debugging('No instanceid provided to action_url_addons, this mean we will not be able to retrieve any' .
- 'instance specific data in the subplugins.');
- }
- } else {
- global $DB;
- $record = $DB->get_record(mod_instance_helper::SUBPLUGIN_TABLE, [
- 'bigbluebuttonbnid' => $instanceid,
- ]);
- if ($record) {
- $metadata['additionalparams'] = $record->additionalparams ?? '';
+ global $DB;
+ if ($instanceid) {
+ $instance = instance::get_from_instanceid($instanceid);
+ $flexurlrecords = $DB->get_records(mod_instance_helper::SUBPLUGIN_TABLE, [
+ 'bigbluebuttonbnid' => $instanceid,
+ ]);
+ $eventtypes = array_flip(utils::ACTION_CODES);
+ foreach ($flexurlrecords as $flexurlrecord) {
+ if ($flexurlrecord->eventtype != utils::ACTION_CODES['all'] &&
+ $eventtypes[$flexurlrecord->eventtype] != $action) {
+ continue;
}
+
+ $metadata[$flexurlrecord->paramname] = utils::get_value_for_field($flexurlrecord->paramvalue, $instance);
+
}
}
-
return ['data' => $data, 'metadata' => $metadata];
}
}
diff --git a/classes/bigbluebuttonbn/mod_form_addons.php b/classes/bigbluebuttonbn/mod_form_addons.php
index 7e259bd..ec40d02 100644
--- a/classes/bigbluebuttonbn/mod_form_addons.php
+++ b/classes/bigbluebuttonbn/mod_form_addons.php
@@ -27,6 +27,50 @@
* @author Laurent David (laurent@call-learning.fr)
*/
class mod_form_addons extends \mod_bigbluebuttonbn\local\extension\mod_form_addons {
+
+ /**
+ * Constructor
+ *
+ * @param \MoodleQuickForm $mform
+ * @param stdClass|null $bigbluebuttonbndata
+ * @param string|null $suffix
+ */
+ public function __construct(\MoodleQuickForm &$mform, ?stdClass $bigbluebuttonbndata = null, string $suffix = null) {
+ parent::__construct($mform, $bigbluebuttonbndata, $suffix);
+ // Supplement BBB data with additional information.
+ if (!empty($bigbluebuttonbndata->id)) {
+ $data = $this->retrieve_additional_data($bigbluebuttonbndata->id);
+ $this->bigbluebuttonbndata = (object) array_merge((array) $this->bigbluebuttonbndata, $data);
+ $this->bigbluebuttonbndata->flexurl_paramcount = count($data);
+ }
+ }
+
+ /**
+ * Retrieve data from the database if any.
+ *
+ * @param int $id
+ * @return array
+ */
+ private function retrieve_additional_data(int $id): array {
+ global $DB;
+ $data = [];
+ $flexurlrecords = $DB->get_records(mod_instance_helper::SUBPLUGIN_TABLE, [
+ 'bigbluebuttonbnid' => $id,
+ ]);
+ if ($flexurlrecords) {
+ $flexurlrecords = array_values($flexurlrecords);
+ foreach ($flexurlrecords as $flexurlrecord) {
+ foreach (utils::PARAM_TYPES as $paramtype => $paramtypevalue) {
+ if (!isset($data["flexurl_{$paramtype}"])) {
+ $data["flexurl_{$paramtype}"] = [];
+ }
+ $data["flexurl_{$paramtype}"][] = $flexurlrecord->{$paramtype} ?? '';
+ }
+ }
+ }
+ return $data;
+ }
+
/**
* Allows modules to modify the data returned by form get_data().
* This method is also called in the bulk activity completion form.
@@ -49,21 +93,8 @@ public function data_postprocessing(\stdClass &$data): void {
public function data_preprocessing(?array &$defaultvalues): void {
// This is where we can add the data from the flexurl table to the data provided.
if (!empty($defaultvalues['id'])) {
- global $DB;
- $flexurlrecords = $DB->get_records(mod_instance_helper::SUBPLUGIN_TABLE, [
- 'bigbluebuttonbnid' => $defaultvalues['id'],
- ]);
- if ($flexurlrecords) {
- $flexurlrecords = array_values($flexurlrecords);
- foreach($flexurlrecords as $flexurlrecord) {
- foreach (utils::PARAM_TYPES as $paramtype => $paramtypevalue) {
- if (!isset($defaultvalues["flexurl_{$paramtype}"])) {
- $defaultvalues["flexurl_{$paramtype}"] = [];
- }
- $defaultvalues["flexurl_{$paramtype}"][] = $flexurlrecord->{$paramtype} ?? '';
- }
- }
- }
+ $data = $this->retrieve_additional_data(intval($defaultvalues['id']));
+ $defaultvalues = (object) array_merge($defaultvalues, $data);
}
}
@@ -101,7 +132,7 @@ public function completion_rule_enabled(array $data): bool {
public function definition_after_data() {
// After data.
$isdeleting = optional_param_array('flexurl_paramdelete', [], PARAM_RAW);
- //// Get the index of the delete button that was pressed.
+ // Get the index of the delete button that was pressed.
if (!empty($isdeleting)) {
$firstindex = array_key_first($isdeleting);
// Then reassign values from the deleted group to the previous group.
@@ -133,7 +164,7 @@ public function definition_after_data() {
public function add_fields(): void {
$this->mform->addElement('header', 'flexurl', get_string('pluginname', 'bbbext_flexurl'));
- $paramcount = optional_param('flexurl_paramcount', $this->bigbluebuttonbndata->paramcount ?? 0, PARAM_RAW);
+ $paramcount = optional_param('flexurl_paramcount', $this->bigbluebuttonbndata->flexurl_paramcount ?? 0, PARAM_RAW);
$paramcount += optional_param('flexurl_addparamgroup', 0, PARAM_RAW) ? 1 : 0;
$isdeleting = optional_param_array('flexurl_paramdelete', [], PARAM_RAW);
foreach ($isdeleting as $index => $value) {
@@ -141,45 +172,45 @@ public function add_fields(): void {
$this->mform->registerNoSubmitButton("flexurl_paramdelete[$index]");
}
for ($index = 0; $index < $paramcount; $index++) {
- $paramtype = $this->mform->createElement(
- 'select',
- "flexurl_eventtype[$index]",
- get_string('param_eventtype', 'bbbext_flexurl'),
- utils::get_option_for_eventtype(),
- ['multiple' => true, 'size' => '2']
- );
$paramname = $this->mform->createElement(
'text',
"flexurl_paramname[$index]",
get_string('param_name', 'bbbext_flexurl'),
- ['size' => '8']
+ ['size' => '6']
);
$paramvalue = $this->mform->createElement(
'selectgroups',
"flexurl_paramvalue[$index]",
get_string('param_value', 'bbbext_flexurl'),
utils::get_options_for_parameters(),
- ['size' => '1']
);
-
+ $paramtype = $this->mform->createElement(
+ 'select',
+ "flexurl_eventtype[$index]",
+ get_string('param_eventtype', 'bbbext_flexurl'),
+ utils::get_option_for_eventtype(),
+ );
$paramdelete = $this->mform->createElement(
'submit',
"flexurl_paramdelete[$index]",
get_string('delete'),
+ [],
+ false,
+ ['customclassoverride' => 'btn-sm btn-secondary float-left']
);
$this->mform->addGroup(
[
- $paramtype, $paramname, $paramvalue, $paramdelete,
+ $paramname, $paramvalue, $paramtype, $paramdelete,
],
"flexurl_paramgroup[$index]",
get_string('paramgroup', 'bbbext_flexurl'),
[' '],
false
);
- $this->mform->setType("flexurl_paramname[$index]", PARAM_TEXT);
- $this->mform->setType("flexurl_paramvalue[$index]", PARAM_RAW);
- $this->mform->setType("flexurl_eventtype[$index]", PARAM_RAW);
+ $this->mform->setType("flexurl_paramname[$index]", utils::PARAM_TYPES['paramname']);
+ $this->mform->setType("flexurl_paramvalue[$index]", utils::PARAM_TYPES['paramvalue']);
+ $this->mform->setType("flexurl_eventtype[$index]", utils::PARAM_TYPES['eventtype']);
$this->mform->setType("flexurl_paramdelete[$index]", PARAM_RAW);
$this->mform->registerNoSubmitButton("flexurl_paramdelete[$index]");
}
@@ -201,8 +232,10 @@ public function add_fields(): void {
*/
public function validation(array $data, array $files): array {
$errors = [];
- if (strip_tags($data['additionalparams']) != $data['additionalparams']) {
- $errors['additionalparams'] = get_string('additionalparams:error', 'bbbext_flexurl');
+ foreach (utils::PARAM_TYPES as $paramtype => $paramtypevalue) {
+ if (clean_param_array($data['flexurl_' . $paramtype], $paramtypevalue, true) === false) {
+ $errors["flexurl_{$paramtype}"] = get_string('invalidvalue', 'bbbext_flexurl');
+ }
}
return $errors;
}
diff --git a/classes/bigbluebuttonbn/mod_instance_helper.php b/classes/bigbluebuttonbn/mod_instance_helper.php
index d8cbf33..986f032 100644
--- a/classes/bigbluebuttonbn/mod_instance_helper.php
+++ b/classes/bigbluebuttonbn/mod_instance_helper.php
@@ -27,7 +27,9 @@
* @author Laurent David (laurent@call-learning.fr)
*/
class mod_instance_helper extends \mod_bigbluebuttonbn\local\extension\mod_instance_helper {
- // This is the name of the table that will be used to store additional data for the instance.
+ /**
+ * This is the name of the table that will be used to store additional data for the instance.
+ */
const SUBPLUGIN_TABLE = 'bbbext_flexurl';
/**
@@ -39,37 +41,9 @@ public function add_instance(stdClass $bigbluebuttonbn) {
$this->sync_additional_params($bigbluebuttonbn);
}
- /**
- * Runs any processes that must be run after a bigbluebuttonbn insert/update.
- *
- * @param stdClass $bigbluebuttonbn BigBlueButtonBN form data
- **/
- public function update_instance(stdClass $bigbluebuttonbn): void {
- $this->sync_additional_params($bigbluebuttonbn);
- }
-
- /**
- * Runs any processes that must be run after a bigbluebuttonbn delete.
- *
- * @param int $id
- */
- public function delete_instance(int $id): void {
- global $DB;
- $DB->delete_records(self::SUBPLUGIN_TABLE, [
- 'bigbluebuttonbnid' => $id,
- ]);
- }
-
- /**
- * Get any join table name that is used to store additional data for the instance.
- * @return array
- */
- public function get_join_tables(): array {
- return [self::SUBPLUGIN_TABLE];
- }
-
/**
* Make sure that the bbbext_flexurl has the right parameters (and not more)
+ *
* @param stdClass $bigbluebuttonbn
* @return void
*/
@@ -77,12 +51,16 @@ private function sync_additional_params(stdClass $bigbluebuttonbn): void {
global $DB;
// Checks first.
$count = $bigbluebuttonbn->flexurl_paramcount ?? 0;
- foreach(utils::PARAM_TYPES as $type =>$paramtype) {
+ foreach (utils::PARAM_TYPES as $type => $paramtype) {
+ if (!isset($bigbluebuttonbn->{'flexurl_' . $type})) {
+ return;
+ }
if ($count != count($bigbluebuttonbn->{'flexurl_' . $type})) {
debugging('FlexURL : The number of ' . $type . ' does not match the number of parameters.');
return;
}
- if (clean_param_array($bigbluebuttonbn->{'flexurl_' . $type}, $paramtype, true) != $bigbluebuttonbn->{'flexurl_' . $type}) {
+ if (clean_param_array($bigbluebuttonbn->{'flexurl_' . $type}, $paramtype, true) !=
+ $bigbluebuttonbn->{'flexurl_' . $type}) {
debugging('FlexURL : The ' . $type . ' contains invalid value.');
return;
}
@@ -91,13 +69,43 @@ private function sync_additional_params(stdClass $bigbluebuttonbn): void {
// First delete everything related to this module.
$DB->delete_records(self::SUBPLUGIN_TABLE, ['bigbluebuttonbnid' => $bigbluebuttonbn->id]);
- for($index = 0; $index < $count; $index++) {
+ for ($index = 0; $index < $count; $index++) {
$queryfields = [];
- foreach(array_keys(utils::PARAM_TYPES) as $type) {
+ foreach (array_keys(utils::PARAM_TYPES) as $type) {
$queryfields[$type] = $bigbluebuttonbn->{'flexurl_' . $type}[$index];
}
$queryfields['bigbluebuttonbnid'] = $bigbluebuttonbn->id;
$DB->insert_record(self::SUBPLUGIN_TABLE, (object) $queryfields);
}
}
+
+ /**
+ * Runs any processes that must be run after a bigbluebuttonbn insert/update.
+ *
+ * @param stdClass $bigbluebuttonbn BigBlueButtonBN form data
+ **/
+ public function update_instance(stdClass $bigbluebuttonbn): void {
+ $this->sync_additional_params($bigbluebuttonbn);
+ }
+
+ /**
+ * Runs any processes that must be run after a bigbluebuttonbn delete.
+ *
+ * @param int $id
+ */
+ public function delete_instance(int $id): void {
+ global $DB;
+ $DB->delete_records(self::SUBPLUGIN_TABLE, [
+ 'bigbluebuttonbnid' => $id,
+ ]);
+ }
+
+ /**
+ * Get any join table name that is used to store additional data for the instance.
+ *
+ * @return array
+ */
+ public function get_join_tables(): array {
+ return []; // We don't make the join here as we have several values per instance.
+ }
}
diff --git a/classes/utils.php b/classes/utils.php
index fbb32b0..fca7686 100644
--- a/classes/utils.php
+++ b/classes/utils.php
@@ -17,6 +17,7 @@
use core_course\external\course_module_summary_exporter;
use core_course\external\course_summary_exporter;
+use mod_bigbluebuttonbn\instance;
/**
* Utility class
@@ -27,12 +28,20 @@
* @author Laurent David (laurent@call-learning.fr)
*/
class utils {
+ /**
+ * Types of actions
+ */
+ const ACTION_CODES = [
+ 'create' => 2,
+ 'join' => 1,
+ 'all' => 8,
+ ];
/**
* Types of additional parameters
*/
public const PARAM_TYPES = [
- 'eventtype' => PARAM_ALPHA,
- 'paramname' => PARAM_ALPHA,
+ 'eventtype' => PARAM_INT,
+ 'paramname' => PARAM_ALPHANUMEXT,
'paramvalue' => PARAM_RAW,
];
@@ -45,11 +54,13 @@ public static function get_options_for_parameters(): array {
$parametertypes = self::get_parameter_types();
$options = [];
$selectedptypes = explode(',', get_config('bbbext_flexurl', 'available_info'));
+ $selectedptypes = array_map('trim', $selectedptypes);
foreach ($parametertypes as $key => $value) {
if (in_array($key, $selectedptypes)) {
$options[$value] = self::get_fields_for_parameter($key);
}
}
+ ksort($options);
return $options;
}
@@ -63,23 +74,68 @@ public static function get_parameter_types(): array {
return [
'activityinfo' => get_string('activity_info', 'bbbext_flexurl'),
'courseinfo' => get_string('course_info', 'bbbext_flexurl'),
- 'userinfo' => get_string('user_info', 'bbbext_flexurl'),
+ 'user' => get_string('user_info', 'bbbext_flexurl'),
];
}
+ /**
+ * Get fields for parameter
+ *
+ * @param string $key
+ * @return array
+ */
public static function get_fields_for_parameter(string $key): array {
if (method_exists(self::class, 'get_' . $key . '_fields')) {
- return call_user_func(self::class . '::get_' . $key . '_fields');
+ $fields = call_user_func(self::class . '::get_' . $key . '_fields');
+ ksort($fields);
+ return array_combine($fields, $fields);
} else {
return [];
}
}
+ /**
+ * Get value for field
+ *
+ * @param string $field
+ * @param instance $instance
+ * @return string
+ */
+ public static function get_value_for_field(string $field, instance $instance): string {
+ // Split the string before the first dot (this will be the type) and the other will be the name of the field.
+ [$fieldtype, $fieldname] = explode('.', $field);
+ if (method_exists(self::class, 'get_' . $fieldtype . '_value')) {
+ return call_user_func(self::class . '::get_' . $fieldtype . '_value', $fieldname, $instance);
+ } else {
+ return '';
+ }
+ }
+
/**
* Get user fields prefixed by user.
+ *
+ * @param string $fieldname
+ * @param instance $instance
+ * @return string
+ */
+ public static function get_user_value(string $fieldname, instance $instance): string {
+ global $USER;
+ $fields = self::get_user_fields();
+ if (!in_array('user.' . $fieldname, $fields)) {
+ return '';
+ }
+ $userwithfields = \core_user::get_user($USER->id);
+ return $userwithfields->$fieldname ?? '';
+ }
+
+ /**
+ * Get user fields prefixed by user.
+ *
+ * For now we only return simple fields located in core_user definition.
+ *
* @return string[]
*/
- public static function get_userinfo_fields() {
+ public static function get_user_fields() {
$userfields = \core_user\fields::get_identity_fields(\context_system::instance());
$userfields = array_merge($userfields, \core_user\fields::get_name_fields());
sort($userfields);
@@ -91,6 +147,25 @@ function($field) {
);
}
+ /**
+ * Course information
+ *
+ * @param string $fieldname
+ * @param instance $instance
+ * @return string
+ */
+ public static function get_courseinfo_value(string $fieldname, instance $instance) {
+ global $PAGE;
+ $fields = self::get_courseinfo_fields();
+ if (!in_array('courseinfo.' . $fieldname, $fields)) {
+ return '';
+ }
+ $exporter =
+ new course_summary_exporter($instance->get_course(), ['context' => $instance->get_context()->get_course_context()]);
+ $coursedata = $exporter->export($PAGE->get_renderer('core'));
+ return $coursedata->$fieldname ?? '';
+ }
+
/**
* Course information
*
@@ -105,6 +180,24 @@ function($field) {
);
}
+ /**
+ * Activity information
+ *
+ * @param string $fieldname
+ * @param instance $instance
+ * @return string
+ */
+ public static function get_activityinfo_value(string $fieldname, instance $instance) {
+ global $PAGE;
+ $fields = self::get_activityinfo_fields();
+ if (!in_array('activityinfo.' . $fieldname, $fields)) {
+ return '';
+ }
+ $exporter = new course_module_summary_exporter(null, ['cm' => $instance->get_cm()]);
+ $moduledata = $exporter->export($PAGE->get_renderer('core'));
+ return $moduledata->$fieldname ?? '';
+ }
+
/**
* Activity information
*
@@ -126,8 +219,9 @@ function($field) {
*/
public static function get_option_for_eventtype() {
return [
- 1 => get_string('event_join', 'bbbext_flexurl'),
- 2 => get_string('event_create', 'bbbext_flexurl'),
+ self::ACTION_CODES['create'] => get_string('event_join', 'bbbext_flexurl'),
+ self::ACTION_CODES['join'] => get_string('event_create', 'bbbext_flexurl'),
+ self::ACTION_CODES['all'] => get_string('event_all', 'bbbext_flexurl'),
];
}
}
diff --git a/db/install.xml b/db/install.xml
index e4f6c58..9b37145 100644
--- a/db/install.xml
+++ b/db/install.xml
@@ -8,7 +8,7 @@
-
+
diff --git a/lang/en/bbbext_flexurl.php b/lang/en/bbbext_flexurl.php
index ff93c84..c776a9a 100644
--- a/lang/en/bbbext_flexurl.php
+++ b/lang/en/bbbext_flexurl.php
@@ -30,6 +30,7 @@
$string['course_info'] = 'Course info (COURSE)';
$string['event_create'] = 'Create';
$string['event_join'] = 'Join';
+$string['event_all'] = 'All';
$string['user_info'] = 'Basic user info (USER)';
$string['pluginname'] = 'BigBlueButton FlexURL';
$string['paramgroup'] = 'Parameter';
diff --git a/tests/bigbluebutton/action_url_addons_tests.php b/tests/bigbluebutton/action_url_addons_tests.php
new file mode 100644
index 0000000..43f1898
--- /dev/null
+++ b/tests/bigbluebutton/action_url_addons_tests.php
@@ -0,0 +1,97 @@
+.
+namespace bbbext_flexurl\bigbluebuttonbn;
+
+use bbbext_flexurl\utils;
+use mod_bigbluebuttonbn\extension;
+use mod_bigbluebuttonbn\external\get_join_url;
+use mod_bigbluebuttonbn\instance;
+
+/**
+ * Action URL addons tests
+ *
+ * @package bbbext_flexurl
+ * @copyright 2023 onwards, Blindside Networks Inc
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @author Laurent David (laurent@call-learning.fr)
+ */
+class action_url_addons_tests extends \advanced_testcase {
+ /**
+ * @var \stdClass $bbb
+ */
+ protected $bbb;
+ /**
+ * @var \stdClass $course
+ */
+ protected $course;
+ /**
+ * @var \stdClass $user
+ */
+ protected $user;
+
+ /**
+ * Setup
+ */
+ public function setUp(): void {
+ global $DB;
+ $this->resetAfterTest();
+ $datagenerator = $this->getDataGenerator();
+ $this->course = $datagenerator->create_course(['fullname' => 'BBBCourse FULL', 'shortname' => 'BBBCourse']);
+ $this->user = $datagenerator->create_user(['firstname' => 'BBB User FN', 'lastname' => 'BBB LN',
+ 'email' => 'bbb@blindsidenetworks.com', ]);
+ $bbbgenerator = $datagenerator->get_plugin_generator('mod_bigbluebuttonbn');
+ $this->bbb = $bbbgenerator->create_instance(['name' => 'BBB Activity', 'course' => $this->course->id]);
+ set_config('available_info', 'user, courseinfo, activityinfo', 'bbbext_flexurl');
+ $datagenerator->enrol_user($this->user->id, $this->course->id);
+ $DB->insert_record('bbbext_flexurl',
+ ['bigbluebuttonbnid' => $this->bbb->id, 'eventtype' => utils::ACTION_CODES['create'], 'paramname' => 'firstname',
+ 'paramvalue' => 'user.firstname', ]);
+ $DB->insert_record('bbbext_flexurl',
+ ['bigbluebuttonbnid' => $this->bbb->id, 'eventtype' => utils::ACTION_CODES['join'], 'paramname' => 'lastname',
+ 'paramvalue' => 'user.lastname', ]);
+ $DB->insert_record('bbbext_flexurl',
+ ['bigbluebuttonbnid' => $this->bbb->id, 'eventtype' => utils::ACTION_CODES['all'], 'paramname' => 'coursename',
+ 'paramvalue' => 'courseinfo.fullname', ]);
+ }
+
+ /**
+ * Test join URL
+ *
+ * @return void
+ */
+ public function test_join_url_has_options() {
+ $this->setUser($this->user);
+ $instance = instance::get_from_instanceid($this->bbb->id);
+ $joinurl = get_join_url::execute($instance->get_cm_id());
+ $this->assertStringContainsString('lastname', $joinurl['join_url']);
+ $this->assertStringContainsString('coursename', $joinurl['join_url']);
+ $this->assertStringContainsString('BBB+LN', $joinurl['join_url']);
+ }
+
+ /**
+ * Test create URL
+ *
+ * @return void
+ */
+ public function test_create_url_has_options() {
+ $this->setUser($this->user);
+ instance::get_from_instanceid($this->bbb->id);
+ $addons = extension::action_url_addons('create', [], ['bbb-meta' => 'Test'], $this->bbb->id);
+ $this->assertContains('firstname', array_keys($addons['metadata']));
+ $this->assertContains('coursename', array_keys($addons['metadata']));
+ $this->assertNotContains('lastname', array_keys($addons['metadata']));
+ }
+}
diff --git a/tests/utils_test.php b/tests/utils_test.php
new file mode 100644
index 0000000..27d7ac1
--- /dev/null
+++ b/tests/utils_test.php
@@ -0,0 +1,193 @@
+.
+namespace bbbext_flexurl;
+
+use mod_bigbluebuttonbn\instance;
+
+/**
+ * BBB Utils tests class.
+ *
+ * @package bbbext_flexurl
+ * @copyright 2023 onwards, Blindside Networks Inc
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @author Laurent David (laurent@call-learning.fr)
+ * @coversDefaultClass \bbbext_flexurl\utils
+ */
+class utils_test extends \advanced_testcase {
+ /**
+ * @var \stdClass $bbb
+ */
+ protected $bbb;
+ /**
+ * @var \stdClass $course
+ */
+ protected $course;
+ /**
+ * @var \stdClass $user
+ */
+ protected $user;
+
+ /**
+ * Provider for get_fields_for_parameter
+ *
+ * @return array[]
+ */
+ public static function provider_get_fields_for_parameter(): array {
+ return [
+ 'actitivityinfo' => [
+ 'activityinfo',
+ ["activityinfo.id", "activityinfo.name", "activityinfo.url", "activityinfo.iconurl"], ],
+ 'courseinfo' => ['courseinfo',
+ ["courseinfo.id", "courseinfo.fullname", "courseinfo.shortname", "courseinfo.idnumber", "courseinfo.summary",
+ "courseinfo.summaryformat", "courseinfo.startdate", "courseinfo.enddate", "courseinfo.visible",
+ "courseinfo.showactivitydates", "courseinfo.showcompletionconditions", "courseinfo.pdfexportfont",
+ "courseinfo.fullnamedisplay", "courseinfo.viewurl", "courseinfo.courseimage", "courseinfo.progress",
+ "courseinfo.hasprogress", "courseinfo.isfavourite", "courseinfo.hidden", "courseinfo.timeaccess",
+ "courseinfo.showshortname", "courseinfo.coursecategory", ], ],
+ 'user' => ['user', ['user.alternatename', 'user.email', 'user.firstname', 'user.firstnamephonetic', 'user.lastname',
+ 'user.lastnamephonetic', 'user.middlename', ], ],
+ ];
+ }
+
+ /**
+ * Provider for get_fields_for_parameter
+ *
+ * @return array[]
+ */
+ public static function provider_get_value_for_fields(): array {
+ return [
+ 'actitivityinfo' => [
+ ["activityinfo.name" => "BBB Activity",
+ "activityinfo.url" => "https://www.example.com/moodle/mod/bigbluebuttonbn/view.php",
+ "activityinfo.iconurl" => "https://www.example.com/moodle/theme/image.php/boost/bigbluebuttonbn",
+ ], ],
+ 'courseinfo' => [
+ [
+ "courseinfo.fullname" => "BBBCourse FULL",
+ "courseinfo.shortname" => "BBBCourse",
+ "courseinfo.idnumber" => "",
+ "courseinfo.summary" => "Test course 1",
+ ], ],
+ 'user' => [[
+ 'user.email' => "",
+ 'user.firstname' => "BBB User FN",
+ 'user.lastname' => "BBB LN",
+ ], ],
+ ];
+ }
+
+ /**
+ * Setup
+ */
+ public function setUp(): void {
+ $this->resetAfterTest();
+ $datagenerator = $this->getDataGenerator();
+ $this->course = $datagenerator->create_course(['fullname' => 'BBBCourse FULL', 'shortname' => 'BBBCourse']);
+ $this->user = $datagenerator->create_user(['firstname' => 'BBB User FN', 'lastname' => 'BBB LN',
+ 'email' => 'bbb@blindsidenetworks.com', ]);
+ $bbbgenerator = $datagenerator->get_plugin_generator('mod_bigbluebuttonbn');
+ $this->bbb = $bbbgenerator->create_instance(['name' => 'BBB Activity', 'course' => $this->course->id]);
+ set_config('available_info', 'user, courseinfo, activityinfo', 'bbbext_flexurl');
+ $datagenerator->enrol_user($this->user->id, $this->course->id);
+ }
+
+ /**
+ * Test get_options_for_parameters
+ *
+ * @covers \bbbext_flexurl\utils::get_options_for_parameters
+ */
+ public function test_get_options_for_parameters() {
+ $this->setAdminUser(); // To get the email.
+ $options = utils::get_options_for_parameters();
+ $this->assertNotEmpty($options);
+ $this->assertEquals(
+ json_decode('{
+"Activity information (ACTIVITY)": {
+ "activityinfo.id": "activityinfo.id",
+ "activityinfo.name": "activityinfo.name",
+ "activityinfo.url": "activityinfo.url",
+ "activityinfo.iconurl": "activityinfo.iconurl"
+},
+"Course info (COURSE)": {
+ "courseinfo.id": "courseinfo.id",
+ "courseinfo.fullname": "courseinfo.fullname",
+ "courseinfo.shortname": "courseinfo.shortname",
+ "courseinfo.idnumber": "courseinfo.idnumber",
+ "courseinfo.summary": "courseinfo.summary",
+ "courseinfo.summaryformat": "courseinfo.summaryformat",
+ "courseinfo.startdate": "courseinfo.startdate",
+ "courseinfo.enddate": "courseinfo.enddate",
+ "courseinfo.visible": "courseinfo.visible",
+ "courseinfo.showactivitydates": "courseinfo.showactivitydates",
+ "courseinfo.showcompletionconditions": "courseinfo.showcompletionconditions",
+ "courseinfo.pdfexportfont": "courseinfo.pdfexportfont",
+ "courseinfo.fullnamedisplay": "courseinfo.fullnamedisplay",
+ "courseinfo.viewurl": "courseinfo.viewurl",
+ "courseinfo.courseimage": "courseinfo.courseimage",
+ "courseinfo.progress": "courseinfo.progress",
+ "courseinfo.hasprogress": "courseinfo.hasprogress",
+ "courseinfo.isfavourite": "courseinfo.isfavourite",
+ "courseinfo.hidden": "courseinfo.hidden",
+ "courseinfo.timeaccess": "courseinfo.timeaccess",
+ "courseinfo.showshortname": "courseinfo.showshortname",
+ "courseinfo.coursecategory": "courseinfo.coursecategory"
+},
+"Basic user info (USER)": {
+ "user.alternatename": "user.alternatename",
+ "user.email": "user.email",
+ "user.firstname": "user.firstname",
+ "user.firstnamephonetic": "user.firstnamephonetic",
+ "user.lastname": "user.lastname",
+ "user.lastnamephonetic": "user.lastnamephonetic",
+ "user.middlename": "user.middlename"
+}
+}', true)
+ , $options);
+ }
+
+ /**
+ * Test get_fields_for_parameter
+ *
+ * @param string $paramtype
+ * @param array $expected
+ *
+ * @covers \bbbext_flexurl\utils::get_fields_for_parameter
+ * @dataProvider provider_get_fields_for_parameter
+ */
+ public function test_get_fields_for_parameter(string $paramtype, array $expected) {
+ $this->setAdminUser(); // To get the email.
+ $fields = utils::get_fields_for_parameter($paramtype);
+ $this->assertNotEmpty($fields);
+ $this->assertEquals($expected, array_keys($fields));
+ }
+
+ /**
+ * Test get_value_for_field
+ *
+ * @param array $expected
+ * @covers \bbbext_flexurl\utils::get_value_for_field
+ * @dataProvider provider_get_value_for_fields
+ */
+ public function test_get_value_for_field(array $expected) {
+ $instance = instance::get_from_instanceid($this->bbb->id);
+
+ $this->setUser($this->user);
+ foreach ($expected as $key => $expectedvalue) {
+ $fieldvalue = utils::get_value_for_field($key, $instance);
+ $this->assertStringContainsString($expectedvalue, $fieldvalue, "Field $key does not contain $expectedvalue");
+ }
+ }
+}