MDL-73225 mod_bigbluebuttonbn: Improve error message when joining

Display more friendly messages when:
    * When displaying activity and the server is not available
    * When we join a meeting and the server is not available or an error is detected
This commit is contained in:
Laurent David 2022-03-03 17:47:38 +01:00
parent 6c114e2a80
commit bad2e0bb54
8 changed files with 81 additions and 17 deletions

View File

@ -60,6 +60,8 @@ class meeting_info extends external_api {
* @param int $groupid
* @param bool $updatecache
* @return array
* @throws \moodle_exception
* @throws restricted_context_exception
*/
public static function execute(
int $bigbluebuttonbnid,
@ -91,7 +93,8 @@ class meeting_info extends external_api {
// Check if the BBB server is working.
$serverversion = bigbluebutton_proxy::get_server_version();
if ($serverversion === null) {
throw new \moodle_exception('general_error_no_answer',
throw new \moodle_exception('general_error_no_answer', 'mod_bigbluebuttonbn',
bigbluebutton_proxy::get_server_not_available_url($instance),
bigbluebutton_proxy::get_server_not_available_message($instance));
}
return (array) meeting::get_meeting_info_for_instance($instance, $updatecache);

View File

@ -19,7 +19,7 @@ namespace mod_bigbluebuttonbn\local\exceptions;
use mod_bigbluebuttonbn\plugin;
/**
* Class bigbluebutton_exception generic exception
* Class bigbluebutton_exception generic exception. This is supposed to be recoverable.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc

View File

@ -19,6 +19,9 @@ namespace mod_bigbluebuttonbn\local\exceptions;
/**
* Class server_not_available_exception
*
* This kind of error cannot be recovered and should be displayed to the user
* signaling that there is an error in the configuration.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later

View File

@ -340,11 +340,16 @@ class bigbluebutton_proxy extends proxy_base {
* @param instance $instance
*/
public static function require_working_server(instance $instance): void {
$version = null;
try {
self::get_server_version();
$version = self::get_server_version();
} catch (server_not_available_exception $e) {
self::handle_server_not_available($instance);
}
if (empty($version)) {
self::handle_server_not_available($instance);
}
}
/**
@ -384,7 +389,7 @@ class bigbluebutton_proxy extends proxy_base {
*/
public static function get_server_not_available_url(instance $instance): string {
if ($instance->is_admin()) {
return new moodle_url('/admin/settings.php', ['section' => 'modsettingbigbluebuttonbn']);
return new moodle_url('/admin/settings.php', ['section' => 'mod_bigbluebuttonbn_general']);
} else if ($instance->is_moderator()) {
return new moodle_url('/course/view.php', ['id' => $instance->get_course_id()]);
} else {

View File

@ -149,7 +149,9 @@ class curl extends \curl {
return $xml;
}
debugging('Issue retrieving information from the server: ' . $response, DEBUG_DEVELOPER);
$debugabstract = html_to_text($response);
$debugabstract = substr($debugabstract, 0, 1024); // Limit to small amount of info so we do not overload logs.
debugging('Issue retrieving information from the server: ' . $debugabstract, DEBUG_DEVELOPER);
return null;
}
}

View File

@ -40,7 +40,7 @@ abstract class proxy_base {
* Sometimes the server sends back some error and errorKeys that
* can be converted to Moodle error messages
*/
const MEETING_ERROR = [
const BBB_TO_MOODLE_ERROR_CODE = [
'checksumError' => 'index_error_checksum',
'notFound' => 'general_error_not_found',
'maxConcurrent' => 'view_error_max_concurrent',
@ -101,31 +101,61 @@ abstract class proxy_base {
* @throws server_not_available_exception
*/
protected static function assert_returned_xml($xml, ?array $additionaldetails = null): void {
if (empty($xml)) {
$messagekey = '';
if (!empty($xml)) {
$messagekey = (string) ($xml->messageKey ?? '');
}
if (empty($xml) || static::is_known_server_unavailable_errorcode($messagekey)) {
$errorcode = self::get_errorcode_from_xml_messagekey($messagekey);
throw new server_not_available_exception(
'general_error_no_answer',
$errorcode,
plugin::COMPONENT,
(new moodle_url('/admin/settings.php?section=modsettingbigbluebuttonbn'))->out()
(new moodle_url('/admin/settings.php?section=modsettingbigbluebuttonbn'))->out(),
);
}
// If it is a checksum error, this is equivalent to the server not being available.
// So we treat it the same way as if there is not answer.
if (is_bool($xml) && $xml) {
// Nothing to do here, this might be a post returning that everything went well.
return;
}
if ((string) $xml->returncode == 'FAILED') {
$messagekey = (string) $xml->messageKey ?? '';
$errorcode = self::get_errorcode_from_xml_messagekey($messagekey);
if (!$additionaldetails) {
$additionaldetails = [];
}
$additionaldetails['xmlmessage'] = (string) $xml->message ?? '';
if (empty($messagekey) || empty(self::MEETING_ERROR[$messagekey])) {
$messagekey = 'general_error_unable_connect';
}
throw new bigbluebutton_exception($messagekey, json_encode($additionaldetails));
throw new bigbluebutton_exception($errorcode, json_encode($additionaldetails));
}
}
/**
* Get Moodle error code from returned Message Key
*
* @param string $messagekey
* @return string
*/
private static function get_errorcode_from_xml_messagekey(string $messagekey): string {
$errorcode = 'general_error_no_answer';
if ($messagekey) {
$errorcode = self::BBB_TO_MOODLE_ERROR_CODE[$messagekey] ?? $errorcode;
}
return $errorcode;
}
/**
* Get Moodle error code from returned Message Key
*
* @param string $messagekey
* @return string
*/
private static function is_known_server_unavailable_errorcode(string $messagekey): string {
// For now, only checksumError is supposed to mean that the server is unavailable.
// Other errors are recoverable.
return in_array($messagekey, ['checksumError']);
}
/**
* Fetch the XML from an endpoint and test for success.
*

View File

@ -30,9 +30,11 @@ use core_calendar\local\event\entities\action_interface;
use mod_bigbluebuttonbn\completion\custom_completion;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\bigbluebutton;
use mod_bigbluebuttonbn\local\exceptions\server_not_available_exception;
use mod_bigbluebuttonbn\local\helpers\files;
use mod_bigbluebuttonbn\local\helpers\mod_helper;
use mod_bigbluebuttonbn\local\helpers\reset;
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
use mod_bigbluebuttonbn\logger;
use mod_bigbluebuttonbn\meeting;
use mod_bigbluebuttonbn\recording;
@ -482,8 +484,20 @@ function mod_bigbluebuttonbn_core_calendar_provide_event_action(
$instance = instance::get_from_instanceid($bigbluebuttonbn->id);
// Get if the room is available.
$roomavailable = $instance->is_currently_open();
// Get if the user can join.
$meetinginfo = meeting::get_meeting_info_for_instance($instance);
$meetinginfo = null;
// Check first if the server can be contacted.
try {
if (empty(bigbluebutton_proxy::get_server_version())) {
// In this case we should already have debugging message printed.
return null;
}
// Get if the user can join.
$meetinginfo = meeting::get_meeting_info_for_instance($instance);
} catch (moodle_exception $e) {
debugging('Error - Cannot retrieve info from meeting ('.$instance->get_meeting_id().') ' . $e->getMessage());
return null;
}
$usercanjoin = $meetinginfo->canjoin;
// Check if the room is closed and the user has already joined this session or played the record.

View File

@ -26,6 +26,7 @@
*/
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\exceptions\server_not_available_exception;
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
use mod_bigbluebuttonbn\logger;
use mod_bigbluebuttonbn\output\view_page;
@ -78,6 +79,12 @@ $PAGE->set_heading($course->fullname);
// Output starts.
$renderer = $PAGE->get_renderer('mod_bigbluebuttonbn');
try {
$renderedinfo = $renderer->render(new view_page($instance));
} catch (server_not_available_exception $e) {
bigbluebutton_proxy::handle_server_not_available($instance);
}
echo $OUTPUT->header();
// Validate if the user is in a role allowed to join.
@ -92,7 +99,7 @@ if (!$instance->can_join() && $instance->get_type() != instance::TYPE_RECORDING_
}
}
echo $renderer->render(new view_page($instance));
echo $renderedinfo;
// Output finishes.
echo $OUTPUT->footer();