first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,149 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\config;
use mod_bigbluebuttonbn\local\helpers\roles;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renderable for the import page.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Darko Miletic (darko.miletic [at] gmail [dt] com)
*/
class import_view implements renderable, templatable {
/**
* @var instance $destinationinstance
*/
protected $destinationinstance;
/**
* @var int|null $sourceinstanceid the source instance id or null if it is not yet set.
*/
protected $sourceinstanceid;
/**
* @var int|null $sourcecourseid the source instance id or null if it is not yet set.
*/
protected $sourcecourseid;
/**
* import_view constructor.
*
* @param instance $destinationinstance
* @param int $sourcecourseid
* @param int $sourceinstanceid
*/
public function __construct(instance $destinationinstance, int $sourcecourseid, int $sourceinstanceid) {
$this->destinationinstance = $destinationinstance;
$this->sourcecourseid = $sourcecourseid >= 0 ? $sourcecourseid : null;
$this->sourceinstanceid = $sourceinstanceid >= 0 ? $sourceinstanceid : null;
}
/**
* Defer to template.
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
$courses = roles::import_get_courses_for_select($this->destinationinstance);
if (config::get('importrecordings_from_deleted_enabled')) {
$courses[0] = get_string('recordings_from_deleted_activities', 'mod_bigbluebuttonbn');
ksort($courses);
}
$context = (object) [
'bbbid' => $this->destinationinstance->get_instance_id(),
'has_recordings' => true,
'bbbsourceid' => 0
];
if (!empty($this->sourceinstanceid)) {
$context->sourceid = $this->sourceinstanceid;
$context->search = [
'value' => ''
];
$sourceinstance = instance::get_from_instanceid($this->sourceinstanceid);
if ($sourceinstance->is_type_room_only()) {
$context->has_recordings = false;
}
$context->bbbsourceid = $sourceinstance->get_instance_id();
}
// Now the selects.
if (!empty($this->sourcecourseid)) {
$selectrecords = [];
$cms = get_fast_modinfo($this->sourcecourseid)->instances['bigbluebuttonbn'];
foreach ($cms as $cm) {
if ($cm->id == $this->destinationinstance->get_cm_id()) {
// Skip the target instance.
continue;
}
if ($cm->deletioninprogress) {
// Check if the BBB is not currently scheduled for deletion.
continue;
}
$selectrecords[$cm->instance] = $cm->name;
}
if (config::get('importrecordings_from_deleted_enabled')) {
$selectrecords[0] =
get_string('recordings_from_deleted_activities', 'mod_bigbluebuttonbn');
}
$actionurl = $this->destinationinstance->get_import_url();
$actionurl->param('sourcecourseid', $this->sourcecourseid);
$select = new \single_select(
$actionurl,
'sourcebn',
$selectrecords,
$this->sourceinstanceid ?? ""
);
$context->bbb_select = $select->export_for_template($output);
}
$context->sourcecourseid = $this->sourcecourseid ?? 0;
// Course selector.
$context->course_select = (new \single_select(
$this->destinationinstance->get_import_url(),
'sourcecourseid',
$courses,
$this->sourcecourseid ?? ""
))->export_for_template($output);
if (!is_null($this->sourcecourseid)) {
$context->has_selected_course = true;
}
// Back button.
$context->back_button = (new \single_button(
$this->destinationinstance->get_view_url(),
get_string('view_recording_button_return', 'mod_bigbluebuttonbn')
))->export_for_template($output);
return $context;
}
}
@@ -0,0 +1,222 @@
<?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\output;
use html_table;
use html_writer;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\meeting;
use mod_bigbluebuttonbn\plugin;
use renderable;
use renderer_base;
use stdClass;
/**
* Renderer for the Index page.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class index implements renderable {
/** @var stdClass */
protected $course;
/** @var stdClass[] */
protected $instances;
/**
* Constructor for the index renderable.
*
* @param stdClass $course
* @param instance[] List of bbbbn instances
*/
public function __construct(stdClass $course, array $instances) {
$this->course = $course;
$this->instances = $instances;
}
/**
* Get the table for the index page.
*
* @param renderer_base $output
* @return html_table
*/
public function get_table(renderer_base $output): html_table {
// Print the list of instances.
$table = new html_table();
if (course_format_uses_sections($this->course->format)) {
$sectionheading = get_string('sectionname', "format_{$this->course->format}");
} else {
$sectionheading = '';
}
$table->head = [
$sectionheading,
get_string('index_heading_name', plugin::COMPONENT),
get_string('index_heading_group', plugin::COMPONENT),
get_string('index_heading_users', plugin::COMPONENT),
get_string('index_heading_viewer', plugin::COMPONENT),
get_string('index_heading_moderator', plugin::COMPONENT),
get_string('index_heading_recording', plugin::COMPONENT),
get_string('index_heading_actions', plugin::COMPONENT),
];
$table->align = ['center', 'left', 'center', 'center', 'center', 'center', 'center'];
foreach ($this->instances as $instance) {
$this->add_instance_to_table($output, $table, $instance);
}
return $table;
}
/**
* Add details of the bigbluebuttonbn instance to the table.
*
* @param renderer_base $output
* @param html_table $table
* @param instance $instance
*/
protected function add_instance_to_table(renderer_base $output, html_table $table, instance $instance): void {
$cm = $instance->get_cm();
if (!$cm->uservisible) {
return;
}
if (groups_get_activity_groupmode($cm) == 0) {
$table->data[] = $this->add_room_row_to_table($output, $instance);
} else {
// Add 'All participants' room information.
$table->data[] = $this->add_room_row_to_table($output, $instance, 0);
// Add data for the groups belonging to the bbb instance, if any.
$groups = groups_get_activity_allowed_groups($cm);
foreach ($groups as $group) {
$table->data[] = $this->add_room_row_to_table($output, $instance, $group->id);
}
}
}
/**
* Displays the general view.
*
* @param renderer_base $output
* @param instance $instance
* @param int|null $group
* @return array
*/
protected function add_room_row_to_table(renderer_base $output, instance $instance, ?int $group = null): array {
if ($group) {
$instance = instance::get_group_instance_from_instance($instance, $group);
}
$meeting = new meeting($instance);
if (course_format_uses_sections($this->course->format)) {
$sectionname = get_section_name($this->course, $instance->get_cm()->sectionnum);
} else {
$sectionname = '';
}
$viewurl = $instance->get_view_url();
if ($groupid = $instance->get_group_id()) {
$viewurl->param('group', $groupid);
}
$joinurl = html_writer::link($viewurl, format_string($instance->get_meeting_name()));
// The meeting info was returned.
if ($meeting->is_running()) {
return [
$sectionname,
$joinurl,
$instance->get_group_name(),
$this->get_room_usercount($meeting),
$this->get_room_attendee_list($meeting, 'VIEWER'),
$this->get_room_attendee_list($meeting, 'MODERATOR'),
$this->get_room_record_info($output, $instance),
$this->get_room_actions($output, $instance, $meeting),
];
}
return [$sectionname, $joinurl, $instance->get_group_name(), '', '', '', '', ''];
}
/**
* Count the number of users in the meeting.
*
* @param meeting $meeting
* @return int
*/
protected function get_room_usercount(meeting $meeting): int {
return count($meeting->get_attendees());
}
/**
* Returns attendee list.
*
* @param meeting $meeting
* @param string $role
* @return string
*/
protected function get_room_attendee_list(meeting $meeting, string $role): string {
$attendees = [];
// Iterate attendees, matching by their "role" property.
foreach ($meeting->get_attendees() as $attendee) {
if (strcmp((string) $attendee['role'], $role) === 0) {
$attendees[] = $attendee['fullName'];
}
}
return implode(', ', $attendees);
}
/**
* Returns indication of recording enabled.
*
* @param renderer_base $output
* @param instance $instance
* @return string
*/
protected function get_room_record_info(renderer_base $output, instance $instance): string {
if ($instance->is_recorded()) {
// If it has been set when meeting created, set the variable on/off.
return get_string('index_enabled', 'bigbluebuttonbn');
}
return '';
}
/**
* Returns room actions.
*
* @param renderer_base $output
* @param instance $instance
* @param meeting $meeting
* @return string
*/
protected function get_room_actions(renderer_base $output, instance $instance, meeting $meeting): string {
if ($instance->is_moderator()) {
return $output->render_from_template('mod_bigbluebuttonbn/end_session_button', (object) [
'bigbluebuttonbnid' => $instance->get_instance_id(),
'groupid' => $instance->get_group_id(),
'statusrunning' => $meeting->is_running(),
]);
}
return '';
}
}
@@ -0,0 +1,79 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\helpers\roles;
use moodle_url;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renderable for the instance notification updated message
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Darko Miletic (darko.miletic [at] gmail [dt] com)
*/
class instance_updated_message implements renderable, templatable {
/** @var int The activity was created */
const TYPE_CREATED = 0;
/** @var int The activity was updated */
const TYPE_UPDATED = 1;
/**
* @var instance $instance
*/
protected $instance;
/** @var int activity type. */
protected $type;
/**
* Instance updated constructor
*
* @param instance $instance
* @param int $type
*/
public function __construct(instance $instance, int $type) {
$this->instance = $instance;
$this->type = $type;
}
/**
* Defer to template.
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
return (object) [
'is_update' => $this->type === self::TYPE_UPDATED,
'is_create' => $this->type === self::TYPE_CREATED,
'name' => $this->instance->get_meeting_name(),
'link' => $this->instance->get_view_url()->out(),
'description' => $this->instance->get_meeting_description(),
'openingtime' => $this->instance->get_instance_var('openingtime'),
'closingtime' => $this->instance->get_instance_var('closingtime'),
];
}
}
@@ -0,0 +1,227 @@
<?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/>.
/**
* Mobile output class for bigbluebuttonbn
*
* @package mod_bigbluebuttonbn
* @copyright 2018 onwards, 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\output;
defined('MOODLE_INTERNAL') || die();
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\exceptions\bigbluebutton_exception;
use mod_bigbluebuttonbn\local\exceptions\meeting_join_exception;
use mod_bigbluebuttonbn\local\exceptions\server_not_available_exception;
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
use mod_bigbluebuttonbn\logger;
use mod_bigbluebuttonbn\meeting;
global $CFG;
require_once($CFG->dirroot . '/lib/grouplib.php');
/**
* Mobile output class for bigbluebuttonbn
*
* @package mod_bigbluebuttonbn
* @copyright 2018 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Jesus Federico (jesus [at] blindsidenetworks [dt] com)
*/
class mobile {
/**
* Returns the bigbluebuttonbn course view for the mobile app.
*
* @param mixed $args
* @return array HTML, javascript and other data.
*/
public static function mobile_course_view($args): array {
global $OUTPUT;
$args = (object) $args;
$versionname = $args->appversioncode >= 3950 ? 'latest' : 'ionic3';
$instance = instance::get_from_cmid($args->cmid);
if (!$instance) {
return self::mobile_print_error(get_string('view_error_url_missing_parameters', 'bigbluebuttonbn'));
}
$cm = $instance->get_cm();
$course = $instance->get_course();
// Check activity status.
if ($instance->before_start_time()) {
$message = get_string('view_message_conference_not_started', 'bigbluebuttonbn');
$notstarted = [
'starts_at' => '',
'ends_at' => '',
];
if (!empty($instance->get_instance_var('openingtime'))) {
$notstarted['starts_at'] = sprintf(
'%s: %s',
get_string('mod_form_field_openingtime', 'bigbluebuttonbn'),
userdate($instance->get_instance_var('openingtime'))
);
}
if (!empty($instance->get_instance_var('closingtime'))) {
$notstarted['ends_at'] = sprintf(
'%s: %s',
get_string('mod_form_field_closingtime', 'bigbluebuttonbn'),
userdate($instance->get_instance_var('closingtime'))
);
}
return self::mobile_print_notification($instance, $message, $notstarted);
}
if ($instance->has_ended()) {
$message = get_string('view_message_conference_has_ended', 'bigbluebuttonbn');
return self::mobile_print_notification($instance, $message);
}
// Check if the BBB server is working.
$serverversion = bigbluebutton_proxy::get_server_version();
if ($serverversion === null) {
return self::mobile_print_error(bigbluebutton_proxy::get_server_not_available_message($instance));
}
// Mark viewed by user (if required).
$completion = new \completion_info($course);
$completion->set_module_viewed($cm);
// Validate if the user is in a role allowed to join.
if (!$instance->can_join()) {
return self::mobile_print_error(get_string('view_nojoin', 'bigbluebuttonbn'));
}
// Note: This logic should match bbb_view.php.
// Logic of bbb_view for join to session.
if ($instance->user_must_wait_to_join()) {
// If user is not administrator nor moderator (user is student) and waiting is required.
return self::mobile_print_notification(
$instance,
get_string('view_message_conference_wait_for_moderator', 'bigbluebuttonbn')
);
}
// See if the BBB session is already in progress.
$urltojoin = '';
try {
$urltojoin = meeting::join_meeting($instance);
} catch (meeting_join_exception $e) {
return self::mobile_print_notification($instance, $e->getMessage());
} catch (server_not_available_exception $e) {
return self::mobile_print_error(bigbluebutton_proxy::get_server_not_available_message($instance));
}
// Check groups access and show message.
$msjgroup = [];
$groupmode = groups_get_activity_groupmode($instance->get_cm());
if ($groupmode != NOGROUPS) {
$msjgroup['message'] = get_string('view_mobile_message_groups_not_supported', 'bigbluebuttonbn');
}
$data = [
'bigbluebuttonbn' => $instance->get_instance_data(),
'msjgroup' => $msjgroup,
'urltojoin' => $urltojoin,
'cmid' => $cm->id,
'courseid' => $course->id,
];
// We want to show a notification when user excedded 45 seconds without click button.
$jstimecreatedmeeting = 'setTimeout(function(){
document.getElementById("bigbluebuttonbn-mobile-notifications").style.display = "block";
document.getElementById("bigbluebuttonbn-mobile-join").disabled = true;
document.getElementById("bigbluebuttonbn-mobile-meetingready").style.display = "none";
}, 45000);';
return [
'templates' => [
[
'id' => 'main',
'html' => $OUTPUT->render_from_template("mod_bigbluebuttonbn/mobile_view_page_$versionname", $data),
],
],
'javascript' => $jstimecreatedmeeting,
'otherdata' => '',
'files' => '',
];
}
/**
* Returns the view for errors.
*
* @param string $error Error to display.
* @return array HTML, javascript and otherdata
*/
protected static function mobile_print_error($error): array {
global $OUTPUT;
return [
'templates' => [
[
'id' => 'main',
'html' => $OUTPUT->render_from_template('mod_bigbluebuttonbn/mobile_view_error', [
'error' => $error,
]),
],
],
'javascript' => '',
'otherdata' => '',
'files' => '',
];
}
/**
* Returns the view for messages.
*
* @param instance $instance
* @param string $message Message to display.
* @param array $notstarted Extra messages for not started session.
* @return array HTML, javascript and otherdata
*/
protected static function mobile_print_notification(instance $instance, $message, $notstarted = []): array {
global $OUTPUT, $CFG;
$data = [
'bigbluebuttonbn' => $instance->get_instance_data(),
'cmid' => $instance->get_cm_id(),
'message' => $message,
'not_started' => $notstarted,
];
return [
'templates' => [
[
'id' => 'main',
'html' => $OUTPUT->render_from_template('mod_bigbluebuttonbn/mobile_view_notification', $data),
],
],
'javascript' => file_get_contents($CFG->dirroot . '/mod/bigbluebuttonbn/mobileapp/mobile.notification.js'),
'otherdata' => '',
'files' => ''
];
}
}
@@ -0,0 +1,60 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\recording;
/**
* Renderer for recording name in place editable.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
class recording_description_editable extends recording_editable {
/**
* Specific constructor with the right label/hint for this editable
*
* @param recording $rec
* @param instance $instance
*/
public function __construct(recording $rec, instance $instance) {
parent::__construct($rec, $instance,
get_string('view_recording_description_editlabel', 'mod_bigbluebuttonbn'),
get_string('view_recording_description_edithint', 'mod_bigbluebuttonbn'));
}
/**
* Get the value to display
*
* @param recording $recording a recording
* @return string
*/
public function get_recording_value(recording $recording): string {
$metadescription = $recording->get('description');
return \html_writer::span($metadescription);
}
/**
* Get the type of editable
*/
protected static function get_type() {
return 'description';
}
}
@@ -0,0 +1,137 @@
<?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\output;
use lang_string;
use mod_bigbluebuttonbn\local\bigbluebutton;
use moodle_exception;
use core\output\inplace_editable;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
use mod_bigbluebuttonbn\local\proxy\recording_proxy;
use mod_bigbluebuttonbn\recording;
use stdClass;
/**
* Renderer for recording in place editable.
*
* Generic class
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
abstract class recording_editable extends \core\output\inplace_editable {
/** @var instance The bbb instance */
protected $instance;
/**
* Constructor.
*
* @param recording $rec
* @param instance $instance
* @param string $edithint
* @param string $editlabel
*/
public function __construct(recording $rec, instance $instance, string $edithint, string $editlabel) {
$this->instance = $instance;
$editable = $this->check_capability();
$displayvalue = format_string(
$this->get_recording_value($rec),
true,
[
'context' => $instance->get_context(),
]
);
// Hack here: the ID is the recordID and the meeting ID.
parent::__construct(
'mod_bigbluebuttonbn',
static::get_type(),
$rec->get('id'),
$editable,
$displayvalue,
$displayvalue,
$edithint,
$editlabel
);
}
/**
* Check user can access and or modify this item.
*
* @return bool
* @throws \moodle_exception
*/
protected function check_capability() {
global $USER;
if (!can_access_course($this->instance->get_course(), $USER)) {
throw new moodle_exception('noaccess', 'mod_bigbluebuttonbn');
}
return $this->instance->can_manage_recordings();
}
/**
* Get the type of editable
*/
protected static function get_type() {
return '';
}
/**
* Get the real recording value
*
* @param recording $rec
* @return mixed
*/
abstract public function get_recording_value(recording $rec): string;
/**
* Update the recording with the new value
*
* @param int $itemid
* @param mixed $value
* @return recording_editable
*/
public static function update($itemid, $value) {
$recording = recording::get_record(['id' => $itemid]);
$instance = instance::get_from_instanceid($recording->get('bigbluebuttonbnid'));
require_login($instance->get_course(), true, $instance->get_cm());
require_capability('mod/bigbluebuttonbn:managerecordings', $instance->get_context());
$recording->set(static::get_type(), $value);
$recording->update();
return new static($recording, $instance);
}
/**
* Helper function evaluates if a row for the data used by the recording table is editable.
*
* @return bool
*/
protected function row_editable() {
// Since the request to BBB are cached, it is safe to use the wrapper to check the server version.
return $this->instance->can_manage_recordings()
&& (bigbluebutton_proxy::get_server_version() >= 1.0 || $this->instance->is_blindside_network_server());
}
}
@@ -0,0 +1,60 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\recording;
/**
* Renderer for recording name in place editable.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
class recording_name_editable extends recording_editable {
/**
* Specific constructor with the right label/hint for this editable
*
* @param recording $rec
* @param instance $instance
*/
public function __construct(recording $rec, instance $instance) {
parent::__construct($rec, $instance,
get_string('view_recording_name_editlabel', 'mod_bigbluebuttonbn'),
get_string('view_recording_name_edithint', 'mod_bigbluebuttonbn'));
}
/**
* Get the value to display
*
* @param recording $recording
* @return string
*/
public function get_recording_value(recording $recording): string {
$metaname = $recording->get('name');
return \html_writer::span($metaname);
}
/**
* Get the type of editable
*/
protected static function get_type() {
return 'name';
}
}
@@ -0,0 +1,179 @@
<?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\output;
use mod_bigbluebuttonbn\recording;
use pix_icon;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renderer for recording row actionbar column
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
class recording_row_actionbar implements renderable, templatable {
/**
* @var $recording
*/
protected $recording;
/**
* @var $tools
*/
protected $tools;
/**
* @var array TOOLS_DEFINITION a list of definition for the the specific tools
*/
const TOOL_ACTION_DEFINITIONS = [
'protect' => [
'action' => 'unprotect',
'icon' => 'lock',
'hidewhen' => '!protected',
'requireconfirmation' => true,
'disablewhen' => 'imported'
],
'unprotect' => [
'action' => 'protect',
'icon' => 'unlock',
'hidewhen' => 'protected',
'requireconfirmation' => true,
'disablewhen' => 'imported'
],
'publish' => [
'action' => 'publish',
'icon' => 'show',
'hidewhen' => 'published',
'requireconfirmation' => true,
'disablewhen' => 'imported'
],
'unpublish' => [
'action' => 'unpublish',
'icon' => 'hide',
'hidewhen' => '!published',
'requireconfirmation' => true,
'disablewhen' => 'imported'
],
'delete' => [
'action' => 'delete',
'icon' => 'trash',
'requireconfirmation' => true
],
'import' => [
'action' => 'import',
'icon' => 'import',
]
];
/**
* recording_row_actionbar constructor.
*
* @param recording $recording
* @param array $tools
*/
public function __construct(recording $recording, array $tools) {
$this->recording = $recording;
$this->tools = $tools;
}
/**
* Export for template
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
$context = new stdClass();
$context->id = 'recording-actionbar-' . $this->recording->get('id');
$context->recordingid = $this->recording->get('id');
$context->tools = [];
foreach ($this->tools as $tool) {
if (!empty(self::TOOL_ACTION_DEFINITIONS[$tool])) {
$buttonpayload = self::TOOL_ACTION_DEFINITIONS[$tool];
$conditionalhiding = $buttonpayload['hidewhen'] ?? null;
$disabledwhen = $buttonpayload['disablewhen'] ?? null;
$this->actionbar_update_diplay($buttonpayload, $disabledwhen, $this->recording, 'disabled');
$this->actionbar_update_diplay($buttonpayload, $conditionalhiding, $this->recording);
if (!empty($buttonpayload)) {
$iconortext = '';
$target = $buttonpayload['action'];
if (isset($buttonpayload['target'])) {
$target .= '-' . $buttonpayload['target'];
}
$id = 'recording-' . $target . '-' . $this->recording->get('recordingid');
$iconattributes = [
'id' => $id,
'class' => 'iconsmall',
];
$linkattributes = [
'id' => $id,
'data-action' => $buttonpayload['action'],
'data-require-confirmation' => !empty($buttonpayload['requireconfirmation']),
'class' => 'action-icon'
];
if ($this->recording->get('imported')) {
$linkattributes['data-links'] = recording::count_records(
[
'recordingid' => $this->recording->get('recordingid'),
'imported' => true,
]
);
}
if (isset($buttonpayload['disabled'])) {
$iconattributes['class'] .= ' fa-' . $buttonpayload['disabled'];
$linkattributes['class'] .= ' disabled';
}
$icon = new pix_icon(
'i/' . $buttonpayload['icon'],
get_string('view_recording_list_actionbar_' . $buttonpayload['action'], 'bigbluebuttonbn'),
'moodle',
$iconattributes
);
$iconortext = $output->render($icon);
$actionlink = new \action_link(new \moodle_url('#'), $iconortext, null, $linkattributes);
$context->tools[] = $actionlink->export_for_template($output);
}
}
}
return $context;
}
/**
* Read the settings for this action and disable or hide the tool from the toolbar
*
* @param array $buttonpayload
* @param string $condition
* @param recording $rec
* @param string $value
*/
private function actionbar_update_diplay(&$buttonpayload, $condition, $rec, $value = 'invisible') {
if ($condition) {
$negates = $condition[0] === '!';
$conditionalvariable = ltrim($condition, '!');
if ($rec->get($conditionalvariable) xor $negates) {
$buttonpayload['disabled'] = $value;
}
}
}
}
@@ -0,0 +1,123 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\bigbluebutton\recordings\recording_data;
use mod_bigbluebuttonbn\local\config;
use mod_bigbluebuttonbn\local\helpers\roles;
use mod_bigbluebuttonbn\recording;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renderer for recording row playback column
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
class recording_row_playback implements renderable, templatable {
/**
* @var $instance
*/
protected $instance;
/**
* @var $recording
*/
protected $recording;
/**
* recording_row_playback constructor.
*
* @param recording $rec
* @param instance|null $instance $instance
*/
public function __construct(recording $rec, ?instance $instance) {
$this->instance = $instance ?? null;
$this->recording = $rec;
}
/**
* Export for template
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
$ispublished = $this->recording->get('published');
$recordingid = $this->recording->get('id');
$context = (object) [
'dataimported' => $this->recording->get('imported'),
'id' => 'playbacks-' . $this->recording->get('id'),
'recordingid' => $recordingid,
'additionaloptions' => '',
'playbacks' => [],
];
$playbacks = $this->recording->get('playbacks');
if ($ispublished && $playbacks) {
foreach ($playbacks as $playback) {
if ($this->should_be_included($playback)) {
$linkattributes = [
'id' => "recording-play-{$playback['type']}-{$recordingid}",
'class' => 'btn btn-sm btn-default',
'data-action' => 'play',
'data-target' => $playback['type'],
];
$actionlink = new \action_link(
$playback['url'],
recording_data::type_text($playback['type']),
null,
$linkattributes
);
$context->playbacks[] = $actionlink->export_for_template($output);
}
}
}
return $context;
}
/**
* Helper function renders the link used for recording type in row for the data used by the recording table.
*
* @param array $playback
* @return bool
*/
protected function should_be_included(array $playback): bool {
// All types that are not restricted are included.
if (array_key_exists('restricted', $playback) && strtolower($playback['restricted']) == 'false') {
return true;
}
$canmanagerecordings = roles::has_capability_in_course(
$this->recording->get('courseid'), 'mod/bigbluebuttonbn:managerecordings');
$canviewallformats = roles::has_capability_in_course(
$this->recording->get('courseid'), 'mod/bigbluebuttonbn:viewallrecordingformats');
$issafeformat = false;
// Now check the list of safe formats.
if ($safeformats = config::get('recording_safe_formats')) {
$safeformatarray = str_getcsv($safeformats);
$issafeformat = in_array($playback['type'], $safeformatarray);
}
return ($canmanagerecordings && $canviewallformats) || $issafeformat;
}
}
@@ -0,0 +1,89 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\bigbluebutton\recordings\recording_data;
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
use mod_bigbluebuttonbn\recording;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renderer for recording_row_preview column
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
class recording_row_preview implements renderable, templatable {
/**
* @var $recording
*/
protected $recording;
/**
* recording_row_playback constructor.
*
* @param recording $rec
*/
public function __construct(recording $rec) {
$this->recording = $rec;
}
/**
* Export for template
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
global $CFG;
$context = (object) [
'id' => 'preview-' . $this->recording->get('id'),
'hidden' => !$this->recording->get('published'),
'recordingpreviews' => [],
];
$playbacks = $this->recording->get('playbacks');
foreach ($playbacks as $playback) {
$thumbnails = [];
if (isset($playback['preview'])) {
foreach ($playback['preview'] as $image) {
$url = trim($image['url']);
$validated = bigbluebutton_proxy::is_remote_resource_valid($url);
if ($validated) {
$thumbnails[] = $url . '?' . time();
}
}
if (!empty($thumbnails)) {
$context->recordingpreviews[] = (object) [
'thumbnails' => $thumbnails,
];
}
}
}
return $context;
}
}
@@ -0,0 +1,77 @@
<?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\output;
use mod_bigbluebuttonbn\instance;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renderer for recording section.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent.david [at] call-learning [dt] fr)
*/
class recordings_session implements renderable, templatable {
/**
* @var instance
*/
protected $instance;
/**
* recording_section constructor.
*
* @param instance $instance
*/
public function __construct(instance $instance) {
$this->instance = $instance;
}
/**
* Export for template
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
$isrecordedtype = $this->instance->is_type_room_and_recordings() || $this->instance->is_type_recordings_only();
$context = (object) [
'bbbid' => $this->instance->get_instance_id(),
'groupid' => $this->instance->get_group_id(),
'has_recordings' => $this->instance->is_recorded() && $isrecordedtype,
'searchbutton' => [
'value' => '',
],
];
if ($this->instance->can_import_recordings()) {
$button = new \single_button(
$this->instance->get_import_url(),
get_string('view_recording_button_import', 'mod_bigbluebuttonbn')
);
$context->import_button = $button->export_for_template($output);
}
return $context;
}
}
@@ -0,0 +1,110 @@
<?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\output;
use core\notification;
use core\output\inplace_editable;
use html_table;
use html_writer;
use mod_bigbluebuttonbn\instance;
use plugin_renderer_base;
/**
* Renderer for the mod_bigbluebuttonbn plugin.
*
* @package mod_bigbluebuttonbn
* @copyright 2010 onwards, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Darko Miletic (darko.miletic [at] gmail [dt] com)
*/
class renderer extends plugin_renderer_base {
/**
* Render the index table.
*
* @param index $index
* @return string
*/
protected function render_index(index $index): string {
$this->page->requires->js_call_amd('mod_bigbluebuttonbn/index', 'init');
return html_writer::table($index->get_table($this));
}
/**
* Render the groups selector.
*
* @param instance $instance
* @return string
*/
public function render_groups_selector(instance $instance): string {
$groupmode = groups_get_activity_groupmode($instance->get_cm());
if ($groupmode == NOGROUPS) {
return '';
}
// Separate or visible group mode.
$groups = groups_get_activity_allowed_groups($instance->get_cm());
if (empty($groups)) {
// No groups in this course.
notification::add(get_string('view_groups_nogroups_warning', 'bigbluebuttonbn'), notification::INFO);
return '';
}
// Assign group default values.
if (count($groups) == 0) {
// Only the All participants group exists.
notification::add(get_string('view_groups_notenrolled_warning', 'bigbluebuttonbn'), notification::INFO);
return '';
}
if (count($groups) > 1) {
notification::add(get_string('view_groups_selection_warning', 'bigbluebuttonbn'), notification::INFO);
}
$groupsmenu = groups_print_activity_menu(
$instance->get_cm(),
$instance->get_view_url(),
true
);
return $groupsmenu . '<br><br>';
}
/**
* Render the view page.
*
* @param view_page $page
* @return string
*/
public function render_view_page(view_page $page): string {
return $this->render_from_template(
'mod_bigbluebuttonbn/view_page',
$page->export_for_template($this)
);
}
/**
* Render inplace editable
*
* @param inplace_editable $e
* @return bool|string
*/
public function render_inplace_editable(inplace_editable $e) {
return $this->render_from_template('core/inplace_editable', $e->export_for_template($this));
}
}
@@ -0,0 +1,147 @@
<?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\output;
use core\check\result;
use core\output\notification;
use mod_bigbluebuttonbn\instance;
use mod_bigbluebuttonbn\local\config;
use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy;
use mod_bigbluebuttonbn\meeting;
use renderable;
use renderer_base;
use stdClass;
use templatable;
use tool_task\check\cronrunning;
/**
* View Page template renderable.
*
* @package mod_bigbluebuttonbn
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class view_page implements renderable, templatable {
/** @var instance The instance being rendered */
protected $instance;
/**
* Constructor for the View Page.
*
* @param instance $instance
*/
public function __construct(instance $instance) {
$this->instance = $instance;
}
/**
* Export the content required to render the template.
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
$pollinterval = bigbluebutton_proxy::get_poll_interval();
$templatedata = (object) [
'instanceid' => $this->instance->get_instance_id(),
'pollinterval' => $pollinterval * 1000, // Javascript poll interval is in miliseconds.
'groupselector' => $output->render_groups_selector($this->instance),
'meetingname' => $this->instance->get_meeting_name(),
'description' => $this->instance->get_meeting_description(true),
'joinurl' => $this->instance->get_join_url(),
];
$viewwarningmessage = config::get('general_warning_message');
if ($this->show_view_warning() && !empty($viewwarningmessage)) {
$templatedata->sitenotification = (object) [
'message' => $viewwarningmessage,
'type' => config::get('general_warning_box_type'),
'icon' => [
'pix' => 'i/bullhorn',
'component' => 'core',
],
];
if ($url = config::get('general_warning_button_href')) {
$templatedata->sitenotification->actions = [[
'url' => $url,
'title' => config::get('general_warning_button_text'),
]];
}
}
if ($this->instance->is_feature_enabled('showroom')) {
$roomdata = meeting::get_meeting_info_for_instance($this->instance);
$roomdata->haspresentations = false;
if (!empty($roomdata->presentations)) {
$roomdata->haspresentations = true;
}
$templatedata->room = $roomdata;
}
$templatedata->recordingwarnings = [];
$check = new cronrunning();
$result = $check->get_result();
if ($result->get_status() != result::OK && $this->instance->is_moderator()) {
$templatedata->recordingwarnings[] = (new notification(
get_string('view_message_cron_disabled', 'mod_bigbluebuttonbn',
$result->get_summary()),
notification::NOTIFY_ERROR,
false
))->export_for_template($output);
}
if ($this->instance->is_feature_enabled('showrecordings') && $this->instance->is_recorded()) {
$recordings = new recordings_session($this->instance);
$templatedata->recordings = $recordings->export_for_template($output);
} else if ($this->instance->is_type_recordings_only()) {
$templatedata->recordingwarnings[] = (new notification(
get_string('view_message_recordings_disabled', 'mod_bigbluebuttonbn'),
notification::NOTIFY_WARNING,
false
))->export_for_template($output);
}
return $templatedata;
}
/**
* Whether to show the view warning.
*
* @return bool
*/
protected function show_view_warning(): bool {
if ($this->instance->is_admin()) {
return true;
}
$generalwarningroles = explode(',', config::get('general_warning_roles'));
$userroles = \mod_bigbluebuttonbn\local\helpers\roles::get_user_roles(
$this->instance->get_context(),
$this->instance->get_user_id()
);
foreach ($userroles as $userrole) {
if (in_array($userrole->shortname, $generalwarningroles)) {
return true;
}
}
return false;
}
}