Rename marketplace plugin to meetletacbfree (mdl_modules.name limit + CI table prefixes)

This commit is contained in:
2026-09-01 23:24:11 +03:30
parent 555cd725f7
commit d987994ded
77 changed files with 1497 additions and 1322 deletions
+25 -25
View File
@@ -17,12 +17,12 @@
/**
* Plugin config helpers.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
/**
* Read MeetLet / Adobe Connect global settings.
@@ -38,35 +38,35 @@ class config {
* API endpoint URL (may already include https://.../api/xml).
*/
public static function get_api_url(): string {
return trim((string)get_config('meetletacbmarketplace', 'host'));
return trim((string)get_config('meetletacbfree', 'host'));
}
/**
* Meeting host domain (no protocol).
*/
public static function get_meet_host(): string {
return trim((string)get_config('meetletacbmarketplace', 'meethost'));
return trim((string)get_config('meetletacbfree', 'meethost'));
}
public static function get_port(): int {
$port = (int)get_config('meetletacbmarketplace', 'port');
$port = (int)get_config('meetletacbfree', 'port');
return $port > 0 ? $port : 443;
}
public static function use_https(): bool {
return (bool)get_config('meetletacbmarketplace', 'https');
return (bool)get_config('meetletacbfree', 'https');
}
public static function get_admin_login(): string {
return (string)get_config('meetletacbmarketplace', 'admin_login');
return (string)get_config('meetletacbfree', 'admin_login');
}
public static function get_admin_password(): string {
return (string)get_config('meetletacbmarketplace', 'admin_password');
return (string)get_config('meetletacbfree', 'admin_password');
}
public static function get_http_auth_header(): string {
$h = trim((string)get_config('meetletacbmarketplace', 'admin_httpauth'));
$h = trim((string)get_config('meetletacbfree', 'admin_httpauth'));
return $h !== '' ? $h : 'Generate-Safe-Random-Token';
}
@@ -75,7 +75,7 @@ class config {
* and realign them to mlu{id}. SSO identity itself is always Moodle id.
*/
public static function use_email_login(): bool {
return (bool)get_config('meetletacbmarketplace', 'email_login');
return (bool)get_config('meetletacbfree', 'email_login');
}
/**
@@ -86,14 +86,14 @@ class config {
if (!self::offline_render_active()) {
return false;
}
return (bool)get_config('meetletacbmarketplace', 'auto_offline');
return (bool)get_config('meetletacbfree', 'auto_offline');
}
/**
* Minutes between recording-sync / auto-MP4 cron runs (1–60, default 5).
*/
public static function cron_interval_minutes(): int {
$v = (int)get_config('meetletacbmarketplace', 'cron_interval');
$v = (int)get_config('meetletacbfree', 'cron_interval');
if ($v < 1) {
$v = 5;
}
@@ -114,7 +114,7 @@ class config {
* How auto-MP4 jobs are handed to the Agent.
*/
public static function agent_dispatch_mode(): string {
$v = trim((string)get_config('meetletacbmarketplace', 'agent_dispatch'));
$v = trim((string)get_config('meetletacbfree', 'agent_dispatch'));
return $v === self::DISPATCH_WINDOW ? self::DISPATCH_WINDOW : self::DISPATCH_IMMEDIATE;
}
@@ -124,7 +124,7 @@ class config {
* @return int[]
*/
public static function agent_dispatch_hours(): array {
$raw = (string)get_config('meetletacbmarketplace', 'agent_dispatch_hours');
$raw = (string)get_config('meetletacbfree', 'agent_dispatch_hours');
if ($raw === '') {
$raw = self::DEFAULT_DISPATCH_HOURS;
}
@@ -200,7 +200,7 @@ class config {
public static function apply_cron_interval(): void {
global $DB;
$mins = self::cron_interval_minutes();
$row = $DB->get_record('task_scheduled', ['classname' => '\\mod_meetletacbmarketplace\\task\\sync_recordings']);
$row = $DB->get_record('task_scheduled', ['classname' => '\\mod_meetletacbfree\\task\\sync_recordings']);
if (!$row) {
return;
}
@@ -221,14 +221,14 @@ class config {
* Configured Render Agent / offline listener base URL (may be empty).
*/
public static function agent_url(): string {
return trim((string)get_config('meetletacbmarketplace', 'agent_url'));
return trim((string)get_config('meetletacbfree', 'agent_url'));
}
/**
* Site-wide default meeting UI language (Adobe Connect), empty = server default.
*/
public static function default_meeting_lang(): string {
$v = get_config('meetletacbmarketplace', 'default_meetinglang');
$v = get_config('meetletacbfree', 'default_meetinglang');
if ($v === false || $v === null) {
return '';
}
@@ -239,7 +239,7 @@ class config {
* Site-wide default: block participants until host joins.
*/
public static function default_wait_for_host(): bool {
return (bool)get_config('meetletacbmarketplace', 'default_waitforhost');
return (bool)get_config('meetletacbfree', 'default_waitforhost');
}
/**
@@ -249,7 +249,7 @@ class config {
*/
public static function meeting_lang_options(): array {
return [
'' => get_string('meetinglang_default', 'meetletacbmarketplace'),
'' => get_string('meetinglang_default', 'meetletacbfree'),
'en' => 'English',
'fa' => 'فارسی',
'ar' => 'العربية',
@@ -286,9 +286,9 @@ class config {
return false;
}
$key = 'enable_' . $feature;
$v = get_config('meetletacbmarketplace', $key);
$v = get_config('meetletacbfree', $key);
if ($v === false && $feature === 'mp4') {
$legacy = get_config('meetletacbmarketplace', 'allow_manual_offline');
$legacy = get_config('meetletacbfree', 'allow_manual_offline');
return $legacy === false ? true : (bool)$legacy;
}
// ZIP is opt-in; other features default on when unset.
@@ -305,7 +305,7 @@ class config {
*/
public static function feature_allow_override(string $feature): bool {
$key = 'allow_override_' . $feature;
$v = get_config('meetletacbmarketplace', $key);
$v = get_config('meetletacbfree', $key);
return $v === false ? true : (bool)$v;
}
@@ -367,9 +367,9 @@ class config {
*/
public static function override_state_options(): array {
return [
self::OVERRIDE_INHERIT => get_string('settingstate_inherit', 'meetletacbmarketplace'),
self::OVERRIDE_OFF => get_string('settingstate_disable', 'meetletacbmarketplace'),
self::OVERRIDE_ON => get_string('settingstate_enable', 'meetletacbmarketplace'),
self::OVERRIDE_INHERIT => get_string('settingstate_inherit', 'meetletacbfree'),
self::OVERRIDE_OFF => get_string('settingstate_disable', 'meetletacbfree'),
self::OVERRIDE_ON => get_string('settingstate_enable', 'meetletacbfree'),
];
}
+22 -22
View File
@@ -17,18 +17,18 @@
/**
* Stepwise Adobe Connect connection tests for admin Ajax UI.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
defined('MOODLE_INTERNAL') || die();
use mod_meetletacbmarketplace\api\client;
use mod_meetletacbmarketplace\api\service;
use mod_meetletacbmarketplace\local\usererror;
use mod_meetletacbfree\api\client;
use mod_meetletacbfree\api\service;
use mod_meetletacbfree\local\usererror;
use Throwable;
/**
@@ -42,7 +42,7 @@ class conntest_runner {
*/
public static function reset(): void {
global $SESSION;
$SESSION->meetletacbmarketplace_conntest = [
$SESSION->meetletacbfree_conntest = [
'service' => null,
'meetings' => null,
'scoid' => null,
@@ -58,19 +58,19 @@ class conntest_runner {
public static function run_step(string $step): array {
global $SESSION;
\mod_meetletacbmarketplace\registration\manager::require_registered();
\mod_meetletacbfree\registration\manager::require_registered();
if (empty($SESSION->meetletacbmarketplace_conntest) || $step === 'login') {
if (empty($SESSION->meetletacbfree_conntest) || $step === 'login') {
self::reset();
}
$state = &$SESSION->meetletacbmarketplace_conntest;
$state = &$SESSION->meetletacbfree_conntest;
if (!config::is_configured()) {
return [
'step' => $step,
'label' => get_string('error', 'meetletacbmarketplace'),
'label' => get_string('error', 'meetletacbfree'),
'ok' => false,
'detail' => get_string('notconfigured', 'meetletacbmarketplace'),
'detail' => get_string('notconfigured', 'meetletacbfree'),
'done' => true,
'abort' => true,
];
@@ -91,7 +91,7 @@ class conntest_runner {
default:
return [
'step' => $step,
'label' => get_string('error', 'meetletacbmarketplace'),
'label' => get_string('error', 'meetletacbfree'),
'ok' => false,
'detail' => 'Unknown step',
'done' => true,
@@ -102,7 +102,7 @@ class conntest_runner {
$state['failed'] = true;
return [
'step' => $step,
'label' => get_string('error', 'meetletacbmarketplace'),
'label' => get_string('error', 'meetletacbfree'),
'ok' => false,
'detail' => $e->getMessage(),
'done' => false,
@@ -127,7 +127,7 @@ class conntest_runner {
$service->logout();
return [
'step' => 'login',
'label' => get_string('testlogin', 'meetletacbmarketplace'),
'label' => get_string('testlogin', 'meetletacbfree'),
'ok' => true,
'detail' => '',
'done' => false,
@@ -148,7 +148,7 @@ class conntest_runner {
$service->logout();
return [
'step' => 'folders',
'label' => get_string('testfolders', 'meetletacbmarketplace'),
'label' => get_string('testfolders', 'meetletacbfree'),
'ok' => (bool)$ok,
'detail' => "content={$content} · archives={$archives} · meetings={$meetings}",
'done' => false,
@@ -189,7 +189,7 @@ class conntest_runner {
}
return [
'step' => 'user',
'label' => get_string('testuser', 'meetletacbmarketplace'),
'label' => get_string('testuser', 'meetletacbfree'),
'ok' => (bool)$assigned,
'detail' => '',
'done' => false,
@@ -204,18 +204,18 @@ class conntest_runner {
$sso = new client();
$cookie = $sso->login_external(config::get_admin_login());
$directok = ($cookie !== '');
$directdetail = get_string('testsso_direct_ok', 'meetletacbmarketplace');
$directdetail = get_string('testsso_direct_ok', 'meetletacbfree');
} catch (Throwable $e) {
$msg = $e->getMessage();
$directdetail = get_string('testsso_direct_fail', 'meetletacbmarketplace', usererror::label('sso_01') . ': ' . $msg);
$directdetail = get_string('testsso_direct_fail', 'meetletacbfree', usererror::label('sso_01') . ': ' . $msg);
}
if ($directok && !empty($state['login'])) {
try {
$sso2 = new client();
$sso2->login_external($state['login']);
$directdetail .= ' · ' . get_string('testsso_userok', 'meetletacbmarketplace');
$directdetail .= ' · ' . get_string('testsso_userok', 'meetletacbfree');
} catch (Throwable $e) {
$directdetail .= ' · ' . get_string('testsso_userwarn', 'meetletacbmarketplace');
$directdetail .= ' · ' . get_string('testsso_userwarn', 'meetletacbfree');
}
}
@@ -225,7 +225,7 @@ class conntest_runner {
return [
'step' => 'sso',
'label' => get_string('testsso', 'meetletacbmarketplace'),
'label' => get_string('testsso', 'meetletacbfree'),
'ok' => $directok,
'detail' => $directdetail,
'done' => false,
@@ -253,7 +253,7 @@ class conntest_runner {
self::reset();
return [
'step' => 'cleanup',
'label' => get_string('testmeeting', 'meetletacbmarketplace'),
'label' => get_string('testmeeting', 'meetletacbfree'),
'ok' => $ok,
'detail' => $detail,
'done' => true,
+12 -12
View File
@@ -17,14 +17,14 @@
/**
* Meeting content download helpers (Adobe Connect proxy).
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet <info@meetlet.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use mod_meetletacbmarketplace\api\service;
use mod_meetletacbfree\api\service;
use stdClass;
defined('MOODLE_INTERNAL') || die();
@@ -37,7 +37,7 @@ class content {
* Opaque, HMAC-signed, current-user download URL.
*/
public static function download_url(int $userid, int $cmid, int $scoid): \moodle_url {
return new \moodle_url('/mod/meetletacbmarketplace/download_content.php', [
return new \moodle_url('/mod/meetletacbfree/download_content.php', [
'k' => self::make_download_token($userid, $cmid, $scoid),
]);
}
@@ -50,7 +50,7 @@ class content {
public static function unpack_download_token(string $token): array {
$token = trim($token);
if (!preg_match('/^[A-Za-z0-9_-]+$/', $token)) {
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbmarketplace');
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbfree');
}
$b64 = strtr($token, '-_', '+/');
$pad = strlen($b64) % 4;
@@ -59,12 +59,12 @@ class content {
}
$raw = base64_decode($b64, true);
if ($raw === false || strlen($raw) < 44) {
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbmarketplace');
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbfree');
}
$mac = substr($raw, 0, 32);
$payload = substr($raw, 32);
if (strlen($payload) < 32) {
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbmarketplace');
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbfree');
}
$ids = unpack('Nuid/Ncmid/Ncid/Nexp', substr($payload, 0, 16));
@@ -75,15 +75,15 @@ class content {
$expires = (int)$ids['exp'];
$expected = hash_hmac(
'sha256',
'meetletacbmarketplace-content-v1|' . $userid . ':' . $cmid . ':' . $cid . ':' . $expires . '|' . $nonce,
'meetletacbfree-content-v1|' . $userid . ':' . $cmid . ':' . $cid . ':' . $expires . '|' . $nonce,
self::download_secret(),
true
);
if (!hash_equals($expected, $mac)) {
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbmarketplace');
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbfree');
}
if ($expires < time() || $userid <= 0 || $cmid <= 0 || $cid <= 0) {
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbmarketplace');
throw new \moodle_exception('errorbadcontenttoken', 'meetletacbfree');
}
return ['userid' => $userid, 'cmid' => $cmid, 'cid' => $cid];
}
@@ -183,7 +183,7 @@ class content {
$payload = pack('N4', $userid, $cmid, $scoid, $expires) . $nonce;
$mac = hash_hmac(
'sha256',
'meetletacbmarketplace-content-v1|' . $userid . ':' . $cmid . ':' . $scoid . ':' . $expires . '|' . $nonce,
'meetletacbfree-content-v1|' . $userid . ':' . $cmid . ':' . $scoid . ':' . $expires . '|' . $nonce,
self::download_secret(),
true
);
@@ -191,6 +191,6 @@ class content {
}
protected static function download_secret(): string {
return 'mod_meetletacbmarketplace/content/' . get_site_identifier();
return 'mod_meetletacbfree/content/' . get_site_identifier();
}
}
+15 -15
View File
@@ -17,12 +17,12 @@
/**
* Role-based feature access matrix (site + activity).
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use context;
use stdClass;
@@ -42,7 +42,7 @@ defined('MOODLE_INTERNAL') || die();
* AND optional site/activity visibility switch when mapped.
*
* Do NOT grant access via Moodle capabilities alone (except the base
* mod/meetletacbmarketplace:view gate to open the activity page).
* mod/meetletacbfree:view gate to open the activity page).
* Do NOT special-case admins/hosts outside the matrix.
*
* Adding a new feature:
@@ -245,7 +245,7 @@ class featureaccess {
* Whether the activity form may show a per-activity access matrix.
*/
public static function activity_override_enabled(): bool {
$raw = get_config('meetletacbmarketplace', 'activity_featureaccess');
$raw = get_config('meetletacbfree', 'activity_featureaccess');
if ($raw === false || $raw === null || $raw === '') {
return true;
}
@@ -302,7 +302,7 @@ class featureaccess {
* @return array<string,array<string,int>>
*/
public static function site_matrix(): array {
$raw = get_config('meetletacbmarketplace', 'featureaccess');
$raw = get_config('meetletacbfree', 'featureaccess');
if ($raw === false || $raw === null || $raw === '') {
return self::builtin_defaults();
}
@@ -374,7 +374,7 @@ class featureaccess {
* Use this for tabs, buttons, links, and web-service actions.
*/
public static function allowed(string $feature, context $context, ?stdClass $activity = null, ?int $userid = null): bool {
if (!\mod_meetletacbmarketplace\registration\manager::is_registered()) {
if (!\mod_meetletacbfree\registration\manager::is_registered()) {
return false;
}
$vis = self::visibility_feature($feature);
@@ -388,21 +388,21 @@ class featureaccess {
* Require allowed() or throw.
*/
public static function require_feature(string $feature, context $context, ?stdClass $activity = null): void {
\mod_meetletacbmarketplace\registration\manager::require_registered();
\mod_meetletacbfree\registration\manager::require_registered();
if (self::allowed($feature, $context, $activity)) {
return;
}
$vis = self::visibility_feature($feature);
if ($vis !== null && !config::show_feature($vis, $activity)) {
throw new \moodle_exception('featuredisabled', 'meetletacbmarketplace');
throw new \moodle_exception('featuredisabled', 'meetletacbfree');
}
throw new \moodle_exception('nopermissions', 'error', '', self::feature_label($feature));
}
public static function feature_label(string $feature): string {
$key = 'accessfeature_' . $feature;
if (get_string_manager()->string_exists($key, 'meetletacbmarketplace')) {
return get_string($key, 'meetletacbmarketplace');
if (get_string_manager()->string_exists($key, 'meetletacbfree')) {
return get_string($key, 'meetletacbfree');
}
return $feature;
}
@@ -430,7 +430,7 @@ class featureaccess {
}
protected static function view_capability_for_context(context $context): string {
return 'mod/meetletacbmarketplace:view';
return 'mod/meetletacbfree:view';
}
/**
@@ -444,14 +444,14 @@ class featureaccess {
$matrix = self::normalize($matrix);
$roles = self::role_labels();
$features = self::feature_labels();
$strtogglerow = get_string('accessmatrix_toggle_row', 'meetletacbmarketplace');
$strtogglecol = get_string('accessmatrix_toggle_col', 'meetletacbmarketplace');
$strall = get_string('accessmatrix_all', 'meetletacbmarketplace');
$strtogglerow = get_string('accessmatrix_toggle_row', 'meetletacbfree');
$strtogglecol = get_string('accessmatrix_toggle_col', 'meetletacbfree');
$strall = get_string('accessmatrix_all', 'meetletacbfree');
$html = \html_writer::start_div('meetlet-access-matrix', ['data-meetlet-access-matrix' => '1']);
$html .= \html_writer::start_tag('table', ['class' => 'generaltable meetlet-access-table']);
$head = \html_writer::tag('th', get_string('accessrole', 'meetletacbmarketplace'));
$head = \html_writer::tag('th', get_string('accessrole', 'meetletacbfree'));
foreach ($features as $fkey => $flabel) {
$toggle = \html_writer::tag('button', s($strall), [
'type' => 'button',
+2 -2
View File
@@ -17,12 +17,12 @@
/**
* Local inline SVG icons (air-gapped — no CDN).
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
defined('MOODLE_INTERNAL') || die();
+8 -8
View File
@@ -17,12 +17,12 @@
/**
* Activity instance helpers.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use cm_info;
use context_module;
@@ -49,12 +49,12 @@ class instance {
public $meetingmap;
public static function get_from_cmid(int $cmid, int $groupid = 0): self {
list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'meetletacbmarketplace');
list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'meetletacbfree');
return self::from_cm($cm, $course, $groupid);
}
public static function get_from_instanceid(int $instanceid, int $groupid = 0): self {
list($course, $cm) = get_course_and_cm_from_instance($instanceid, 'meetletacbmarketplace');
list($course, $cm) = get_course_and_cm_from_instance($instanceid, 'meetletacbfree');
return self::from_cm($cm, $course, $groupid);
}
@@ -64,15 +64,15 @@ class instance {
$inst->cm = $cm;
$inst->course = $course;
$inst->context = context_module::instance($cm->id);
$inst->record = $DB->get_record('meetletacbmarketplace', ['id' => $cm->instance], '*', MUST_EXIST);
$inst->record = $DB->get_record('meetletacbfree', ['id' => $cm->instance], '*', MUST_EXIST);
$inst->groupid = $groupid;
$inst->meetingmap = $DB->get_record('meetlet_marketplace_meetings', [
$inst->meetingmap = $DB->get_record('meetletacbfree_meetings', [
'instanceid' => $inst->record->id,
'groupid' => $groupid,
]);
if (!$inst->meetingmap && $groupid !== 0) {
// Fallback to no-group mapping.
$inst->meetingmap = $DB->get_record('meetlet_marketplace_meetings', [
$inst->meetingmap = $DB->get_record('meetletacbfree_meetings', [
'instanceid' => $inst->record->id,
'groupid' => 0,
]);
@@ -87,7 +87,7 @@ class instance {
public function require_meeting(): int {
$scoid = $this->meetingscoid();
if (!$scoid) {
throw new moodle_exception('nomeeting', 'meetletacbmarketplace');
throw new moodle_exception('nomeeting', 'meetletacbfree');
}
return $scoid;
}
+19 -19
View File
@@ -17,14 +17,14 @@
/**
* Meeting lifecycle status (schedule + live presence + wait-for-host).
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use mod_meetletacbmarketplace\api\service;
use mod_meetletacbfree\api\service;
defined('MOODLE_INTERNAL') || die();
@@ -74,30 +74,30 @@ class meetingstatus {
$status = self::CHECKING;
$errorcode = '';
$message = get_string('statuschecking_help', 'meetletacbmarketplace');
$message = get_string('statuschecking_help', 'meetletacbfree');
// Never allow join before Adobe confirms room state.
$joinable = false;
if ($endts > 0 && $endts < $now) {
$status = self::ENDED;
$message = get_string('meetingended', 'meetletacbmarketplace');
$message = get_string('meetingended', 'meetletacbfree');
$errorcode = 'meetingended';
$joinable = $canbypass;
} else if ($startts > $now) {
$status = self::SCHEDULED;
$message = get_string('meetingnotstarted', 'meetletacbmarketplace');
$message = get_string('meetingnotstarted', 'meetletacbfree');
$errorcode = 'meetingnotstarted';
$joinable = $canbypass;
} else if ($waitforhost && !$canbypass) {
// Provisional: assume waiting until Adobe poll confirms a live/open room.
$status = self::WAITINGHOST;
$message = get_string('joinblocked_waitinghost', 'meetletacbmarketplace');
$message = get_string('joinblocked_waitinghost', 'meetletacbfree');
$errorcode = 'waitingforhost';
$joinable = false;
} else if (!$canbypass) {
// Until Adobe confirms the room is live, keep Join disabled for participants.
$status = self::CHECKING;
$message = get_string('statuschecking_help', 'meetletacbmarketplace');
$message = get_string('statuschecking_help', 'meetletacbfree');
$joinable = false;
}
@@ -190,14 +190,14 @@ class meetingstatus {
if (!$canbypass) {
$joinable = false;
$errorcode = 'meetingended';
$message = get_string('meetingended', 'meetletacbmarketplace');
$message = get_string('meetingended', 'meetletacbfree');
}
} else if ($startts > $now) {
$status = self::SCHEDULED;
if (!$canbypass) {
$joinable = false;
$errorcode = 'meetingnotstarted';
$message = get_string('meetingnotstarted', 'meetletacbmarketplace');
$message = get_string('meetingnotstarted', 'meetletacbfree');
}
} else if (!$islive && $checkhost && !$canbypass) {
// Nobody is in the Adobe room yet. Participants must not get a join URL —
@@ -206,12 +206,12 @@ class meetingstatus {
$status = self::WAITINGHOST;
$joinable = false;
$errorcode = 'waitingforhost';
$message = get_string('joinblocked_waitinghost', 'meetletacbmarketplace');
$message = get_string('joinblocked_waitinghost', 'meetletacbfree');
} else if (!$islive && $canbypass && ($waitforhost || $adobehold)) {
// Host/moderator may enter; still show waiting-for-host for clarity.
$status = self::WAITINGHOST;
$joinable = true;
$message = get_string('joinblocked_waitinghost', 'meetletacbmarketplace');
$message = get_string('joinblocked_waitinghost', 'meetletacbfree');
}
if ($service instanceof service) {
@@ -236,7 +236,7 @@ class meetingstatus {
'status' => $status,
'statuslabel' => self::label($status),
'joinable' => $joinable,
'message' => $message !== '' ? $message : get_string('statushelp', 'meetletacbmarketplace'),
'message' => $message !== '' ? $message : get_string('statushelp', 'meetletacbfree'),
'errorcode' => $errorcode,
'starttime' => $startts,
'endtime' => $endts,
@@ -247,17 +247,17 @@ class meetingstatus {
public static function label(string $status): string {
switch ($status) {
case self::LIVE:
return get_string('statuslive', 'meetletacbmarketplace');
return get_string('statuslive', 'meetletacbfree');
case self::ENDED:
return get_string('statusended', 'meetletacbmarketplace');
return get_string('statusended', 'meetletacbfree');
case self::SCHEDULED:
return get_string('statusscheduled', 'meetletacbmarketplace');
return get_string('statusscheduled', 'meetletacbfree');
case self::WAITINGHOST:
return get_string('statuswaitinghost', 'meetletacbmarketplace');
return get_string('statuswaitinghost', 'meetletacbfree');
case self::CHECKING:
return get_string('statuschecking', 'meetletacbmarketplace');
return get_string('statuschecking', 'meetletacbfree');
default:
return get_string('statusopen', 'meetletacbmarketplace');
return get_string('statusopen', 'meetletacbfree');
}
}
}
+4 -4
View File
@@ -17,12 +17,12 @@
/**
* Admin HTML for the in-plugin privacy policy tab (Marketplace edition).
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
defined('MOODLE_INTERNAL') || die();
@@ -35,7 +35,7 @@ class privacy_policy {
* Build privacy policy HTML (safe for admin settings heading).
*/
public static function render(): string {
$plugin = 'meetletacbmarketplace';
$plugin = 'meetletacbfree';
$sections = [
self::section('scope', 'privacy_tab_scope_title', 'privacy_tab_scope_body'),
@@ -67,7 +67,7 @@ class privacy_policy {
* @param string $bodykey Lang string key or pre-formatted body HTML.
*/
protected static function section(string $id, string $titlekey, string $bodykey): string {
$plugin = 'meetletacbmarketplace';
$plugin = 'meetletacbfree';
$title = get_string($titlekey, $plugin);
$body = strpos($bodykey, '<') !== false
? $bodykey
+7 -7
View File
@@ -17,14 +17,14 @@
/**
* Recording list sync (community edition — no offline MP4 / agent).
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet <info@meetlet.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use mod_meetletacbmarketplace\api\service;
use mod_meetletacbfree\api\service;
use stdClass;
defined('MOODLE_INTERNAL') || die();
@@ -58,7 +58,7 @@ class recordings {
$out = [];
foreach ($remote as $rec) {
$record = $DB->get_record('meetlet_marketplace_recordings', [
$record = $DB->get_record('meetletacbfree_recordings', [
'instanceid' => $instance->record->id,
'recordingscoid' => $rec->scoid,
]);
@@ -77,7 +77,7 @@ class recordings {
$record->timestart = $rec->datebegin ? strtotime($rec->datebegin) : 0;
$record->timeend = $rec->dateend ? strtotime($rec->dateend) : 0;
$record->timemodified = $now;
$record->id = $DB->insert_record('meetlet_marketplace_recordings', $record);
$record->id = $DB->insert_record('meetletacbfree_recordings', $record);
} else {
$record->name = $rec->name;
$record->urlpath = $rec->urlpath;
@@ -86,7 +86,7 @@ class recordings {
$record->timestart = $rec->datebegin ? strtotime($rec->datebegin) : 0;
$record->timeend = $rec->dateend ? strtotime($rec->dateend) : 0;
$record->timemodified = $now;
$DB->update_record('meetlet_marketplace_recordings', $record);
$DB->update_record('meetletacbfree_recordings', $record);
}
$record->playurl = config::public_url($rec->urlpath);
@@ -104,7 +104,7 @@ class recordings {
global $DB;
$rows = $DB->get_records(
'meetlet_marketplace_recordings',
'meetletacbfree_recordings',
['instanceid' => $instance->record->id],
'timestart DESC, id DESC'
);
+18 -18
View File
@@ -17,15 +17,15 @@
/**
* BBB-style participant role mapping for Adobe Connect.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use context;
use mod_meetletacbmarketplace\api\service;
use mod_meetletacbfree\api\service;
use stdClass;
defined('MOODLE_INTERNAL') || die();
@@ -101,7 +101,7 @@ class roles {
* Site-wide default participant rules from plugin config (or built-in).
*/
public static function get_site_default_rules(): array {
$raw = get_config('meetletacbmarketplace', 'default_participants');
$raw = get_config('meetletacbfree', 'default_participants');
if (is_string($raw) && $raw !== '') {
$decoded = json_decode($raw, true);
if (is_array($decoded) && !empty($decoded)) {
@@ -251,9 +251,9 @@ class roles {
*/
public static function adobe_role_labels(): array {
return [
self::ROLE_HOST => get_string('role_host', 'meetletacbmarketplace'),
self::ROLE_PRESENTER => get_string('role_presenter', 'meetletacbmarketplace'),
self::ROLE_PARTICIPANT => get_string('role_participant', 'meetletacbmarketplace'),
self::ROLE_HOST => get_string('role_host', 'meetletacbfree'),
self::ROLE_PRESENTER => get_string('role_presenter', 'meetletacbfree'),
self::ROLE_PARTICIPANT => get_string('role_participant', 'meetletacbfree'),
];
}
@@ -270,14 +270,14 @@ class roles {
'class' => 'generaltable meetlet-access-table meetlet-rolemapping-table',
]);
$head = \html_writer::tag('th', get_string('accessrole', 'meetletacbmarketplace'));
$head .= \html_writer::tag('th', get_string('adoberole', 'meetletacbmarketplace'));
$head = \html_writer::tag('th', get_string('accessrole', 'meetletacbfree'));
$head .= \html_writer::tag('th', get_string('adoberole', 'meetletacbfree'));
$html .= \html_writer::tag('thead', \html_writer::tag('tr', $head));
$body = '';
// Everyone row first.
$body .= self::mapping_row_html(
get_string('participant_type_all', 'meetletacbmarketplace'),
get_string('participant_type_all', 'meetletacbfree'),
$inputname . '[_all]',
$matrix['_all'] ?? self::ROLE_PARTICIPANT,
$adobelabels,
@@ -387,15 +387,15 @@ class roles {
public static function get_participant_data(context $context, ?stdClass $instance = null): array {
$data = [
'all' => [
'name' => get_string('participant_type_all', 'meetletacbmarketplace'),
'name' => get_string('participant_type_all', 'meetletacbfree'),
'children' => [],
],
'role' => [
'name' => get_string('participant_type_role', 'meetletacbmarketplace'),
'name' => get_string('participant_type_role', 'meetletacbfree'),
'children' => self::get_roles_select($context),
],
'user' => [
'name' => get_string('participant_type_user', 'meetletacbmarketplace'),
'name' => get_string('participant_type_user', 'meetletacbfree'),
'children' => [],
],
];
@@ -426,9 +426,9 @@ class roles {
public static function get_participant_selection_data(): array {
return [
'type_options' => [
'all' => get_string('participant_type_all', 'meetletacbmarketplace'),
'role' => get_string('participant_type_role', 'meetletacbmarketplace'),
'user' => get_string('participant_type_user', 'meetletacbmarketplace'),
'all' => get_string('participant_type_all', 'meetletacbfree'),
'role' => get_string('participant_type_role', 'meetletacbfree'),
'user' => get_string('participant_type_user', 'meetletacbfree'),
],
'type_selected' => 'role',
'options' => ['all' => '---------------'],
@@ -442,10 +442,10 @@ class roles {
* @return string|null Adobe permission-id or null if denied
*/
public static function resolve_adobe_role(stdClass $instance, context $context, int $userid): ?string {
if (has_capability('mod/meetletacbmarketplace:host', $context, $userid)) {
if (has_capability('mod/meetletacbfree:host', $context, $userid)) {
return service::ROLE_HOST;
}
if (has_capability('mod/meetletacbmarketplace:presenter', $context, $userid)) {
if (has_capability('mod/meetletacbfree:presenter', $context, $userid)) {
return service::ROLE_PRESENTER;
}
+6 -6
View File
@@ -17,17 +17,17 @@
/**
* Track Adobe Connect room occupancy for auto MP4 after the class actually ends.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
defined('MOODLE_INTERNAL') || die();
/**
* Persist live/closed room state on meetlet_marketplace_meetings and decide when to sweep recordings.
* Persist live/closed room state on meetletacbfree_meetings and decide when to sweep recordings.
*/
class roomsession {
/** Seconds to keep looking for new recordings after the room empties. */
@@ -48,7 +48,7 @@ class roomsession {
if (!$map || empty($map->id)) {
return false;
}
$row = $DB->get_record('meetlet_marketplace_meetings', ['id' => (int)$map->id]);
$row = $DB->get_record('meetletacbfree_meetings', ['id' => (int)$map->id]);
if (!$row) {
return false;
}
@@ -59,7 +59,7 @@ class roomsession {
if ($islive) {
$row->islive = 1;
$row->liveat = $now;
$DB->update_record('meetlet_marketplace_meetings', $row);
$DB->update_record('meetletacbfree_meetings', $row);
$instance->meetingmap = $row;
return false;
}
@@ -78,7 +78,7 @@ class roomsession {
$row->sweptat = $now;
}
if ($waslive || $due) {
$DB->update_record('meetlet_marketplace_meetings', $row);
$DB->update_record('meetletacbfree_meetings', $row);
}
$instance->meetingmap = $row;
return $due;
+4 -4
View File
@@ -17,12 +17,12 @@
/**
* Admin HTML for Adobe Connect server setup guide.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
defined('MOODLE_INTERNAL') || die();
@@ -34,7 +34,7 @@ class server_guide {
* Build guide HTML (safe for admin settings heading).
*/
public static function render(): string {
$plugin = 'meetletacbmarketplace';
$plugin = 'meetletacbfree';
$match = \html_writer::tag('h4', get_string('serverguide_match_title', $plugin)) .
\html_writer::tag('p', get_string('serverguide_match_intro', $plugin)) .
@@ -97,7 +97,7 @@ class server_guide {
* Help-code table so an admin can match a student-reported ML- code.
*/
protected static function errorcodes_section(): string {
$plugin = 'meetletacbmarketplace';
$plugin = 'meetletacbfree';
$head = \html_writer::tag('tr',
\html_writer::tag('th', get_string('serverguide_errorcodes_col_code', $plugin)) .
\html_writer::tag('th', get_string('serverguide_errorcodes_col_meaning', $plugin)) .
+6 -6
View File
@@ -17,15 +17,15 @@
/**
* Adobe Connect SSO helpers for the current Moodle user.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet <info@meetlet.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use mod_meetletacbmarketplace\api\client;
use mod_meetletacbmarketplace\api\service;
use mod_meetletacbfree\api\client;
use mod_meetletacbfree\api\service;
use moodle_exception;
use stdClass;
@@ -76,7 +76,7 @@ class sso {
* @param string[] $logincandidates
*/
public static function breeze_session(array $logincandidates): string {
\mod_meetletacbmarketplace\registration\manager::require_registered();
\mod_meetletacbfree\registration\manager::require_registered();
$cookie = '';
$lasterror = null;
@@ -138,7 +138,7 @@ class sso {
* @return array{cookie:string,adobeuser:stdClass}
*/
public static function provision_and_login(stdClass $user, int $scoid, string $permission): array {
\mod_meetletacbmarketplace\registration\manager::require_registered();
\mod_meetletacbfree\registration\manager::require_registered();
$service = new service();
$service->login_admin();
+20 -20
View File
@@ -17,12 +17,12 @@
/**
* Audience-aware MeetLet errors (student vs teacher/admin) with help codes.
*
* @package mod_meetletacbmarketplace
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbmarketplace\local;
namespace mod_meetletacbfree\local;
use moodle_exception;
@@ -55,7 +55,7 @@ class usererror extends moodle_exception {
if ($this->xml !== '') {
$debug['xml'] = $this->xml;
}
parent::__construct($errorcode, 'meetletacbmarketplace', '', null, json_encode($debug, JSON_UNESCAPED_UNICODE));
parent::__construct($errorcode, 'meetletacbfree', '', null, json_encode($debug, JSON_UNESCAPED_UNICODE));
}
/**
@@ -66,9 +66,9 @@ class usererror extends moodle_exception {
'moodle/site:config',
'moodle/course:update',
'moodle/course:manageactivities',
'mod/meetletacbmarketplace:addinstance',
'mod/meetletacbmarketplace:host',
'mod/meetletacbmarketplace:presenter',
'mod/meetletacbfree:addinstance',
'mod/meetletacbfree:host',
'mod/meetletacbfree:presenter',
], $context, $userid);
}
@@ -147,7 +147,7 @@ class usererror extends moodle_exception {
if (!$staff) {
return [
'code' => $label,
'message' => get_string('error_user_unavailable', 'meetletacbmarketplace', $label),
'message' => get_string('error_user_unavailable', 'meetletacbfree', $label),
'detailhtml' => '',
'staff' => false,
];
@@ -312,13 +312,13 @@ class usererror extends moodle_exception {
protected static function staff_title(string $helpid, \Throwable $e): string {
$cat = self::catalog();
$key = $cat[$helpid]['titlekey'] ?? '';
if ($key !== '' && get_string_manager()->string_exists($key, 'meetletacbmarketplace')) {
return get_string($key, 'meetletacbmarketplace');
if ($key !== '' && get_string_manager()->string_exists($key, 'meetletacbfree')) {
return get_string($key, 'meetletacbfree');
}
if ($e instanceof moodle_exception) {
return $e->getMessage();
}
return get_string('error', 'meetletacbmarketplace');
return get_string('error', 'meetletacbfree');
}
/**
@@ -330,12 +330,12 @@ class usererror extends moodle_exception {
$cat = self::catalog();
$titlekey = $cat[$helpid]['titlekey'] ?? '';
$fixkey = $cat[$helpid]['fixkey'] ?? '';
$title = ($titlekey !== '' && get_string_manager()->string_exists($titlekey, 'meetletacbmarketplace'))
? get_string($titlekey, 'meetletacbmarketplace')
: get_string('error', 'meetletacbmarketplace');
$title = ($titlekey !== '' && get_string_manager()->string_exists($titlekey, 'meetletacbfree'))
? get_string($titlekey, 'meetletacbfree')
: get_string('error', 'meetletacbfree');
$codebox = \html_writer::div(
\html_writer::span(get_string('error_helpcode_label', 'meetletacbmarketplace'), 'meetlet-err__codelabel') .
\html_writer::span(get_string('error_helpcode_label', 'meetletacbfree'), 'meetlet-err__codelabel') .
\html_writer::tag('code', s($label), ['data-copy-code' => $label]),
'meetlet-err__codebox'
);
@@ -348,8 +348,8 @@ class usererror extends moodle_exception {
continue;
}
$dtkey = 'errorfact_' . $key;
$dt = get_string_manager()->string_exists($dtkey, 'meetletacbmarketplace')
? get_string($dtkey, 'meetletacbmarketplace')
$dt = get_string_manager()->string_exists($dtkey, 'meetletacbfree')
? get_string($dtkey, 'meetletacbfree')
: $key;
$rows .= \html_writer::tag(
'div',
@@ -372,17 +372,17 @@ class usererror extends moodle_exception {
$factshtml = $rows !== '' ? \html_writer::tag('dl', $rows, ['class' => 'meetlet-err__facts']) : '';
$fix = '';
if ($fixkey !== '' && get_string_manager()->string_exists($fixkey, 'meetletacbmarketplace')) {
$fix = \html_writer::div(get_string($fixkey, 'meetletacbmarketplace'), 'meetlet-err__fix');
if ($fixkey !== '' && get_string_manager()->string_exists($fixkey, 'meetletacbfree')) {
$fix = \html_writer::div(get_string($fixkey, 'meetletacbfree'), 'meetlet-err__fix');
}
$xmlhtml = '';
if ($parsed['xml'] !== '') {
$xmlhtml = \html_writer::tag('p', get_string('error_adobe_response', 'meetletacbmarketplace'), ['class' => 'meetlet-err__prelabel']) .
$xmlhtml = \html_writer::tag('p', get_string('error_adobe_response', 'meetletacbfree'), ['class' => 'meetlet-err__prelabel']) .
\html_writer::tag('pre', s($parsed['xml']), ['class' => 'meetlet-err__xml']);
}
$guide = \html_writer::tag('p', get_string('error_see_serverguide', 'meetletacbmarketplace'), ['class' => 'meetlet-err__guide']);
$guide = \html_writer::tag('p', get_string('error_see_serverguide', 'meetletacbfree'), ['class' => 'meetlet-err__guide']);
return \html_writer::div(
\html_writer::tag('p', s($title), ['class' => 'meetlet-err__lead']) .