AutorÃa | Ultima modificación | Ver Log |
<?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\task;use core\task\adhoc_task;use core\task\manager;use Matrix\Exception;use mod_bigbluebuttonbn\instance;use mod_bigbluebuttonbn\local\proxy\recording_proxy;use mod_bigbluebuttonbn\logger;use mod_bigbluebuttonbn\recording;use moodle_exception;/*** Class containing the scheduled task for converting recordings for the BigBlueButton version 2.5 in Moodle 4.0.** @package mod_bigbluebuttonbn* @copyright 2021 Jesus Federico, Blindside Networks Inc <jesus at blindsidenetworks dot com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class upgrade_recordings_task extends adhoc_task {/*** Run the migration task.*/public function execute() {$info = $this->get_custom_data();$meetingid = $info->meetingid;$isimported = $info->isimported ?? 0;$this->process_bigbluebuttonbn_logs($meetingid, $isimported);}/*** Process all bigbluebuttonbn logs looking for entries which should be converted to meetings.** @param string $meetingid* @param bool $isimported* @return bool Whether any more logs are waiting to be processed* @throws \dml_exception* @throws moodle_exception*/protected function process_bigbluebuttonbn_logs(string $meetingid, bool $isimported): bool {global $DB;$classname = static::class;mtrace("Executing {$classname} for meeting {$meetingid}...");// Fetch the logs queued for upgrade.mtrace("Fetching logs for conversion");// Each log is ordered by timecreated.[$select, $params] = $this->get_sql_query_for_logs($meetingid, $isimported);$logsrs = $DB->get_recordset_select('bigbluebuttonbn_logs',$select,$params,'timecreated DESC','id, meetingid, timecreated, log');if (!$logsrs->valid()) {mtrace("No logs were found for conversion.");// No more logs. Stop queueing.return false;}// Retrieve recordings from the servers for this meeting.$recordings = recording_proxy::fetch_recording_by_meeting_id([$meetingid]);// Sort recordings by meetingId, then startTime.uasort($recordings, function($a, $b) {return $b['startTime'] - $a['startTime'];});// Create an instance of bigbluebuttonbn_recording per valid recording.mtrace("Creating new recording records...");$recordingcount = 0;foreach ($recordings as $recordingid => $recording) {$importeddata = $isimported ? '' : json_encode($recording);try {$instance = instance::get_from_meetingid($recording['meetingID']);} catch (Exception $e) {mtrace("Unable to parse meetingID " . $e->getMessage());continue;}if ($instance) {$newrecording = ['courseid' => $instance->get_course_id(),'bigbluebuttonbnid' => $instance->get_instance_id(),'groupid' => $instance->get_group_id(), // The groupid should be taken from the meetingID.'recordingid' => $recordingid,'status' => recording::RECORDING_STATUS_PROCESSED,];} else {mtrace("Unable to find an activity for {$recording['meetingID']}. This recording is headless.");// This instance does not exist any more.// Use the data in the log instead of the instance.$meetingdata = instance::parse_meetingid($recording['meetingID']);$newrecording = ['courseid' => $meetingdata['courseid'],'bigbluebuttonbnid' => $meetingdata['instanceid'],'groupid' => 0,'recordingid' => $recordingid,'status' => recording::RECORDING_STATUS_PROCESSED,];if (array_key_exists('groupid', $meetingdata)) {$newrecording['groupid'] = $meetingdata['groupid'];}}if ($DB->record_exists('bigbluebuttonbn_recordings', $newrecording)) {mtrace("A recording already exists for {$recording['recordID']}. Skipping.");// A recording matching these characteristics alreay exists.continue;}// Recording has not been imported, check if we still have more logs.// We try to guess which logs matches which recordings are they are classed in the same order.// But this is just an attempt.$log = null;if ($logsrs->valid()) {$log = $logsrs->current();$logsrs->next();}$timecreated = empty($log) ? time() : $log->timecreated;$newrecording['imported'] = $isimported;$newrecording['headless'] = 0;$newrecording['importeddata'] = $importeddata;$newrecording['timecreated'] = $newrecording['timemodified'] = $timecreated;// If we could not match with a log, we still create the recording.$DB->insert_record('bigbluebuttonbn_recordings', $newrecording);$recordingcount++;}mtrace("Migrated {$recordingcount} recordings.");// Now deactivate logs by marking all of them as migrated.// Reason for this is that we don't want to run another migration here and we don't know// which logs matches which recordings.$DB->set_field_select('bigbluebuttonbn_logs', 'log',$isimported ? logger::EVENT_IMPORT_MIGRATED : logger::EVENT_CREATE_MIGRATED,$select,$params);$logsrs->close();return true;}/*** Get the query (records_select) for the logs to convert.** Each log is ordered by timecreated.** @param string $meetingid* @param bool $isimported* @return array*/protected function get_sql_query_for_logs(string $meetingid, bool $isimported): array {global $DB;if ($isimported) {return ['log = :logmatch AND meetingid = :meetingid',['logmatch' => logger::EVENT_IMPORT, 'meetingid' => $meetingid],];}return ['log = :logmatch AND meetingid = :meetingid AND ' . $DB->sql_like('meta', ':match'),['logmatch' => logger::EVENT_CREATE,'match' => '%true%','meetingid' => $meetingid],];}/*** Schedule all upgrading tasks.** @param bool $importedrecordings* @return void* @throws \dml_exception*/public static function schedule_upgrade_per_meeting($importedrecordings = false) {global $DB;$meetingids = $DB->get_fieldset_sql('SELECT DISTINCT meetingid FROM {bigbluebuttonbn_logs} WHERE log = :createorimport',['createorimport' => $importedrecordings ? logger::EVENT_IMPORT : logger::EVENT_CREATE]);foreach ($meetingids as $mid) {$createdrecordingtask = new static();$createdrecordingtask->set_custom_data((object) ['meetingid' => $mid, 'isimported' => $importedrecordings]);manager::queue_adhoc_task($createdrecordingtask);}}}