be252e49e2
Migrate legacy ajax/JS to external services and AMD, enable TLS verification, scope admin CSS with RTLCSS-safe rules, and fix README/lang/boilerplate gaps. Co-authored-by: Cursor <cursoragent@cursor.com>
352 lines
15 KiB
PHP
352 lines
15 KiB
PHP
<?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/>.
|
||
|
||
/**
|
||
* Admin settings for MeetLet Adobe Connect Bridge (tabbed).
|
||
*
|
||
* @package mod_meetletacbfree
|
||
* @copyright 2026 MeetLet <info@meetlet.net>
|
||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||
*/
|
||
|
||
defined('MOODLE_INTERNAL') || die();
|
||
|
||
use mod_meetletacbfree\admin\settingspage_tabs;
|
||
use mod_meetletacbfree\local\config;
|
||
use mod_meetletacbfree\local\conntest_runner;
|
||
use mod_meetletacbfree\local\privacy_policy;
|
||
use mod_meetletacbfree\local\server_guide;
|
||
use mod_meetletacbfree\registration\manager as registration_manager;
|
||
|
||
// Ensure class is available even if Moodle classmap cache is stale after adding this file.
|
||
require_once(__DIR__ . '/classes/local/server_guide.php');
|
||
require_once(__DIR__ . '/classes/local/privacy_policy.php');
|
||
|
||
if ($ADMIN->fulltree) {
|
||
global $OUTPUT;
|
||
|
||
$settings = new settingspage_tabs(
|
||
$settings->name,
|
||
$settings->visiblename,
|
||
$settings->req_capability,
|
||
$settings->hidden
|
||
);
|
||
|
||
$logo = $OUTPUT->image_url('adobeconnect', 'meetletacbfree');
|
||
|
||
$plugin = new stdClass();
|
||
include(__DIR__ . '/version.php');
|
||
$release = $plugin->release ?? '';
|
||
if ($release !== '' && strpos(current_language(), 'fa') === 0) {
|
||
$release = strtr($release, [
|
||
'0' => '۰', '1' => '۱', '2' => '۲', '3' => '۳', '4' => '۴',
|
||
'5' => '۵', '6' => '۶', '7' => '۷', '8' => '۸', '9' => '۹',
|
||
]);
|
||
}
|
||
$versionbadge = $release !== ''
|
||
? html_writer::span(get_string('settingsversion', 'meetletacbfree', $release), 'meetlet-settings-version')
|
||
: '';
|
||
$hero = html_writer::div(
|
||
html_writer::img($logo, 'Adobe Connect', ['alt' => 'Adobe Connect']) .
|
||
html_writer::div(
|
||
html_writer::tag('h3', get_string('pluginname', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('settingsintro', 'meetletacbfree')),
|
||
'meetlet-settings-copy'
|
||
) .
|
||
$versionbadge,
|
||
'meetlet-settings-hero'
|
||
);
|
||
$settings->set_hero($hero);
|
||
|
||
// Tab: Online activation (required before other features work).
|
||
$page = new admin_settingpage('meetletacbfree_registration', get_string('tab_registration', 'meetletacbfree'));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/registrationheading',
|
||
get_string('registration_heading', 'meetletacbfree'),
|
||
get_string('registration_heading_desc', 'meetletacbfree')
|
||
));
|
||
$page->add(new admin_setting_configtext(
|
||
'meetletacbfree/registration_api_url',
|
||
get_string('registration_api_url', 'meetletacbfree'),
|
||
get_string('registration_api_url_desc', 'meetletacbfree'),
|
||
registration_manager::DEFAULT_API_URL,
|
||
PARAM_URL
|
||
));
|
||
$page->add(new \mod_meetletacbfree\admin\setting_registration());
|
||
$settings->add($page);
|
||
|
||
// Tab: Privacy (always visible — read policy before activating).
|
||
$page = new admin_settingpage('meetletacbfree_privacy', get_string('tab_privacy', 'meetletacbfree'));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/privacycard',
|
||
'',
|
||
privacy_policy::render()
|
||
));
|
||
$settings->add($page);
|
||
|
||
$registered = registration_manager::is_registered();
|
||
|
||
if ($registered) {
|
||
|
||
// Tab: Server setup guide.
|
||
$page = new admin_settingpage('meetletacbfree_serverguide', get_string('tab_serverguide', 'meetletacbfree'));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/serverguidecard',
|
||
'',
|
||
server_guide::render()
|
||
));
|
||
$settings->add($page);
|
||
|
||
// Tab 2: Server settings (API / admin / offline listener).
|
||
$page = new admin_settingpage('meetletacbfree_connection', get_string('settings_connection', 'meetletacbfree'));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/connectionheading',
|
||
get_string('settings_connection', 'meetletacbfree'),
|
||
get_string('settings_connection_desc', 'meetletacbfree')
|
||
));
|
||
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/server_api_group',
|
||
'',
|
||
html_writer::div(
|
||
html_writer::tag('h4', get_string('server_group_api', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('server_group_api_desc', 'meetletacbfree')),
|
||
'meetlet-server-group'
|
||
)
|
||
));
|
||
$page->add(new admin_setting_configtext(
|
||
'meetletacbfree/host', get_string('host', 'meetletacbfree'), get_string('host_desc', 'meetletacbfree'),
|
||
'https://connect.example.edu/api/xml', PARAM_URL
|
||
));
|
||
$page->add(new admin_setting_configtext(
|
||
'meetletacbfree/meethost', get_string('meethost', 'meetletacbfree'), get_string('meethost_desc', 'meetletacbfree'),
|
||
'connect.example.edu', PARAM_HOST
|
||
));
|
||
$page->add(new admin_setting_configtext(
|
||
'meetletacbfree/port', get_string('port', 'meetletacbfree'), get_string('port_desc', 'meetletacbfree'),
|
||
'443', PARAM_INT
|
||
));
|
||
$page->add(new admin_setting_configcheckbox(
|
||
'meetletacbfree/https', get_string('https', 'meetletacbfree'), get_string('https_desc', 'meetletacbfree'), 1
|
||
));
|
||
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/server_admin_group',
|
||
'',
|
||
html_writer::div(
|
||
html_writer::tag('h4', get_string('server_group_admin', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('server_group_admin_desc', 'meetletacbfree')),
|
||
'meetlet-server-group'
|
||
)
|
||
));
|
||
$page->add(new admin_setting_configtext(
|
||
'meetletacbfree/admin_login', get_string('admin_login', 'meetletacbfree'), get_string('admin_login_desc', 'meetletacbfree'),
|
||
'', PARAM_RAW_TRIMMED
|
||
));
|
||
$page->add(new admin_setting_configpasswordunmask(
|
||
'meetletacbfree/admin_password', get_string('admin_password', 'meetletacbfree'), get_string('admin_password_desc', 'meetletacbfree'), ''
|
||
));
|
||
$page->add(new admin_setting_configtext(
|
||
'meetletacbfree/admin_httpauth', get_string('admin_httpauth', 'meetletacbfree'), get_string('admin_httpauth_desc', 'meetletacbfree'),
|
||
'Generate-Safe-Random-Token', PARAM_TEXT
|
||
));
|
||
$page->add(new admin_setting_configcheckbox(
|
||
'meetletacbfree/email_login', get_string('email_login', 'meetletacbfree'), get_string('email_login_desc', 'meetletacbfree'), 1
|
||
));
|
||
|
||
$settings->add($page);
|
||
|
||
// Tab 4: Connection test (Ajax).
|
||
$page = new admin_settingpage('meetletacbfree_test', get_string('tab_connectiontest', 'meetletacbfree'));
|
||
$steplabels = [
|
||
'login' => get_string('testlogin', 'meetletacbfree'),
|
||
'folders' => get_string('testfolders', 'meetletacbfree'),
|
||
'user' => get_string('testuser', 'meetletacbfree'),
|
||
'sso' => get_string('testsso', 'meetletacbfree'),
|
||
'cleanup' => get_string('testcleanup', 'meetletacbfree'),
|
||
];
|
||
$testui = html_writer::div(
|
||
html_writer::start_div('meetlet-conntest__hero') .
|
||
html_writer::img($logo, 'Adobe Connect', ['class' => 'meetlet-conntest__logo']) .
|
||
html_writer::tag('h2', get_string('conntesttitle', 'meetletacbfree'), ['class' => 'meetlet-conntest__title']) .
|
||
html_writer::tag('p', get_string('conntestintro', 'meetletacbfree'), ['class' => 'meetlet-conntest__intro']) .
|
||
html_writer::end_div() .
|
||
html_writer::div(
|
||
html_writer::tag('button',
|
||
'<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">'
|
||
. '<path fill="currentColor" d="M8 5v14l11-7z"/></svg>'
|
||
. html_writer::span(get_string('runtest', 'meetletacbfree'), 'meetlet-btn-with-icon__label'),
|
||
[
|
||
'type' => 'button',
|
||
'class' => 'meetlet-settings-btn meetlet-btn-with-icon',
|
||
'data-meetlet-run-test' => '1',
|
||
]
|
||
) .
|
||
html_writer::span('', 'meetlet-conntest__status', ['data-meetlet-test-status' => '1']),
|
||
'meetlet-conntest__actions'
|
||
) .
|
||
html_writer::div(
|
||
html_writer::div(
|
||
html_writer::span('', 'meetlet-conntest__progress-text', ['data-meetlet-progress-label' => '1']),
|
||
'meetlet-conntest__progress-label'
|
||
) .
|
||
html_writer::div(
|
||
html_writer::div('', 'meetlet-conntest__progress-fill', ['data-meetlet-progress-fill' => '1']),
|
||
'meetlet-conntest__progress-track'
|
||
),
|
||
'meetlet-conntest__progress',
|
||
['data-meetlet-progress' => '1', 'hidden' => 'hidden']
|
||
) .
|
||
html_writer::div('', 'meetlet-conntest__grid', ['data-meetlet-test-grid' => '1']),
|
||
'meetlet-conntest',
|
||
[
|
||
'id' => 'meetlet-acb-conntest',
|
||
'data-steps' => implode(',', conntest_runner::STEPS),
|
||
'data-step-labels' => json_encode($steplabels, JSON_UNESCAPED_UNICODE),
|
||
'data-str-ok' => get_string('testok', 'meetletacbfree'),
|
||
'data-str-fail' => get_string('testfail', 'meetletacbfree'),
|
||
'data-str-running' => get_string('testrunning', 'meetletacbfree'),
|
||
'data-str-idle' => '',
|
||
'data-str-waiting' => get_string('testwaiting', 'meetletacbfree'),
|
||
'data-str-runningstep' => get_string('testrunningstep', 'meetletacbfree'),
|
||
'data-str-skipped' => get_string('testskipped', 'meetletacbfree'),
|
||
'data-str-progress' => get_string('testprogress', 'meetletacbfree'),
|
||
]
|
||
);
|
||
$page->add(new admin_setting_heading('meetletacbfree/testui', '', $testui));
|
||
$settings->add($page);
|
||
|
||
// Tab 4: Meeting settings (defaults + feature visibility).
|
||
$page = new admin_settingpage('meetletacbfree_meetings', get_string('tab_meetingsettings', 'meetletacbfree'));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/roomdefaultsheading',
|
||
get_string('roomdefaults', 'meetletacbfree'),
|
||
get_string('roomdefaults_desc', 'meetletacbfree')
|
||
));
|
||
$page->add(new admin_setting_configselect(
|
||
'meetletacbfree/default_meetinglang',
|
||
get_string('default_meetinglang', 'meetletacbfree'),
|
||
get_string('default_meetinglang_desc', 'meetletacbfree'),
|
||
'',
|
||
config::meeting_lang_options()
|
||
));
|
||
$page->add(new admin_setting_configcheckbox(
|
||
'meetletacbfree/default_waitforhost',
|
||
get_string('default_waitforhost', 'meetletacbfree'),
|
||
get_string('default_waitforhost_desc', 'meetletacbfree'),
|
||
0
|
||
));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/featuresheading',
|
||
get_string('featuresheading', 'meetletacbfree'),
|
||
get_string('featuresheading_desc', 'meetletacbfree')
|
||
));
|
||
|
||
$featuregroups = ['recordingstab', 'contenttab'];
|
||
foreach ($featuregroups as $feature) {
|
||
$grouphtml = html_writer::div(
|
||
html_writer::tag('h4', get_string('featuregroup_' . $feature, 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('featuregroup_' . $feature . '_desc', 'meetletacbfree')),
|
||
'meetlet-feature-group'
|
||
);
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/featuregroup_' . $feature,
|
||
'',
|
||
$grouphtml
|
||
));
|
||
// ZIP download is off by default; other features stay on.
|
||
$enabledefault = ($feature === 'zip') ? 0 : 1;
|
||
$page->add(new admin_setting_configcheckbox(
|
||
'meetletacbfree/enable_' . $feature,
|
||
get_string('enable_' . $feature, 'meetletacbfree'),
|
||
get_string('enable_' . $feature . '_desc', 'meetletacbfree'),
|
||
$enabledefault
|
||
));
|
||
$page->add(new admin_setting_configcheckbox(
|
||
'meetletacbfree/allow_override_' . $feature,
|
||
get_string('allow_override_' . $feature, 'meetletacbfree'),
|
||
get_string('allow_override_' . $feature . '_desc', 'meetletacbfree'),
|
||
1
|
||
));
|
||
}
|
||
$settings->add($page);
|
||
|
||
// Tab 5: Role feature access + Adobe room role mapping.
|
||
$page = new admin_settingpage('meetletacbfree_access', get_string('tab_accesssettings', 'meetletacbfree'));
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/rolemappingheading',
|
||
get_string('siterolemapping', 'meetletacbfree'),
|
||
get_string('siterolemapping_desc', 'meetletacbfree')
|
||
));
|
||
$page->add(new \mod_meetletacbfree\admin\setting_rolemapping());
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/accessheading',
|
||
get_string('featureaccess', 'meetletacbfree'),
|
||
get_string('featureaccess_desc', 'meetletacbfree')
|
||
));
|
||
$page->add(new admin_setting_configcheckbox(
|
||
'meetletacbfree/activity_featureaccess',
|
||
get_string('activity_featureaccess', 'meetletacbfree'),
|
||
get_string('activity_featureaccess_desc', 'meetletacbfree'),
|
||
1
|
||
));
|
||
$page->add(new \mod_meetletacbfree\admin\setting_featureaccess());
|
||
$page->add(new admin_setting_heading(
|
||
'meetletacbfree/accessresetassets',
|
||
'',
|
||
\mod_meetletacbfree\admin\access_reset_ui::page_assets()
|
||
));
|
||
$settings->add($page);
|
||
|
||
} // End tabs unlocked after online activation.
|
||
|
||
// Tab: About developer / MeetLet (read-only; always visible).
|
||
$page = new admin_settingpage('meetletacbfree_about', get_string('tab_aboutdev', 'meetletacbfree'));
|
||
$meetletlogo = $OUTPUT->image_url('meetlet_logo', 'meetletacbfree');
|
||
$abouturl = new moodle_url('https://meetlet.net/', [
|
||
'utm_source' => 'moodle',
|
||
'utm_medium' => 'plugin',
|
||
'utm_campaign' => 'meetletacbfree',
|
||
'utm_content' => 'about_developer_tab',
|
||
]);
|
||
$about = html_writer::div(
|
||
html_writer::div(
|
||
html_writer::img($meetletlogo, 'MeetLet', ['alt' => 'MeetLet']),
|
||
'meetlet-about__brand'
|
||
) .
|
||
html_writer::tag('h4', get_string('about_heading', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('about_body_p1', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('about_body_p2', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('about_body_p3', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('about_body_p4', 'meetletacbfree')) .
|
||
html_writer::tag('p', get_string('marketplace_commercial_note', 'meetletacbfree'), [
|
||
'class' => 'meetlet-about__commercial',
|
||
]) .
|
||
html_writer::div(
|
||
html_writer::link($abouturl, get_string('about_visit_website', 'meetletacbfree'), [
|
||
'class' => 'meetlet-about__cta',
|
||
'target' => '_blank',
|
||
'rel' => 'noopener',
|
||
]),
|
||
'meetlet-about__cta-wrap'
|
||
),
|
||
'meetlet-about meetlet-settings-card'
|
||
);
|
||
$page->add(new admin_setting_heading('meetletacbfree/aboutcard', '', $about));
|
||
$settings->add($page);
|
||
|
||
}
|