. /** * Ajax: SSO URL to play or edit a recording in Adobe Connect. * * @package mod_meetletacbfree * @copyright 2026 MeetLet * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_meetletacbfree\external; use core_external\external_api; use core_external\external_function_parameters; use core_external\external_single_structure; use core_external\external_value; use mod_meetletacbfree\api\service; use mod_meetletacbfree\local\config; use mod_meetletacbfree\local\featureaccess; use mod_meetletacbfree\local\instance; use mod_meetletacbfree\local\roles; use mod_meetletacbfree\local\sso; use mod_meetletacbfree\local\usererror; use moodle_exception; defined('MOODLE_INTERNAL') || die(); /** * Prepare Adobe Connect recording play/edit URL with session for current user. */ class get_recording_launch_url extends external_api { public static function execute_parameters(): external_function_parameters { return new external_function_parameters([ 'cmid' => new external_value(PARAM_INT, 'Course module id'), 'recordingscoid' => new external_value(PARAM_INT, 'Recording sco id'), 'mode' => new external_value(PARAM_ALPHA, 'play or edit'), 'groupid' => new external_value(PARAM_INT, 'Group id', VALUE_DEFAULT, 0), ]); } public static function execute(int $cmid, int $recordingscoid, string $mode, int $groupid = 0): array { global $DB, $USER; $params = self::validate_parameters(self::execute_parameters(), [ 'cmid' => $cmid, 'recordingscoid' => $recordingscoid, 'mode' => $mode, 'groupid' => $groupid, ]); $mode = strtolower($params['mode']); if (!in_array($mode, ['play', 'edit'], true)) { throw new moodle_exception('error', 'meetletacbfree'); } \mod_meetletacbfree\registration\manager::require_registered(); $inst = instance::get_from_cmid($params['cmid'], $params['groupid']); self::validate_context($inst->context); require_capability('mod/meetletacbfree:view', $inst->context); featureaccess::require_feature(featureaccess::RECORDINGS, $inst->context, $inst->record); if ($mode === 'edit') { featureaccess::require_feature(featureaccess::ADOBEEDITOR, $inst->context, $inst->record); } $record = $DB->get_record('meetletacbfree_recordings', [ 'instanceid' => $inst->record->id, 'recordingscoid' => $params['recordingscoid'], ]); if (!$record || empty($record->urlpath)) { throw new moodle_exception('norecordings', 'meetletacbfree'); } try { // Prefer meeting role when available; fall back to view for play / host for edit. $adoberole = roles::resolve_adobe_role($inst->record, $inst->context, $USER->id); if ($mode === 'edit') { $permission = ($adoberole === service::ROLE_HOST || $adoberole === service::ROLE_PRESENTER) ? $adoberole : service::ROLE_HOST; } else { $permission = $adoberole ?: service::ROLE_PARTICIPANT; } $auth = sso::provision_and_login($USER, (int)$params['recordingscoid'], $permission); $url = $mode === 'edit' ? config::recording_editor_url((string)$record->urlpath, $auth['cookie']) : config::recording_play_url((string)$record->urlpath, $auth['cookie']); return usererror::ws_ok($url); } catch (\Throwable $e) { if ($e instanceof moodle_exception && in_array($e->errorcode, ['nopermissions', 'requirelogin', 'invalidparameter'], true)) { throw $e; } return usererror::ws_fail($e, $inst->context); } } public static function execute_returns(): external_single_structure { return new external_single_structure(usererror::ws_url_returns()); } }