Files
meetletacbfree/classes/local/conntest_runner.php
T

264 lines
8.7 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/>.
/**
* Stepwise Adobe Connect connection tests for admin Ajax UI.
*
* @package mod_meetletacbfree
* @copyright 2026 MeetLet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_meetletacbfree\local;
defined('MOODLE_INTERNAL') || die();
use mod_meetletacbfree\api\client;
use mod_meetletacbfree\api\service;
use mod_meetletacbfree\local\usererror;
use Throwable;
/**
* Runs connection checks one step at a time (session-backed).
*/
class conntest_runner {
public const STEPS = ['login', 'folders', 'user', 'sso', 'cleanup'];
/**
* Reset session scratch data for a new run.
*/
public static function reset(): void {
global $SESSION;
$SESSION->meetletacbfree_conntest = [
'service' => null,
'meetings' => null,
'scoid' => null,
'principalid' => null,
'login' => null,
'failed' => false,
];
}
/**
* @return array{label:string,ok:bool,detail:string,done:bool,step:string}
*/
public static function run_step(string $step): array {
global $SESSION;
\mod_meetletacbfree\registration\manager::require_registered();
if (empty($SESSION->meetletacbfree_conntest) || $step === 'login') {
self::reset();
}
$state = &$SESSION->meetletacbfree_conntest;
if (!config::is_configured()) {
return [
'step' => $step,
'label' => get_string('error', 'meetletacbfree'),
'ok' => false,
'detail' => get_string('notconfigured', 'meetletacbfree'),
'done' => true,
'abort' => true,
];
}
try {
switch ($step) {
case 'login':
return self::step_login($state);
case 'folders':
return self::step_folders($state);
case 'user':
return self::step_user($state);
case 'sso':
return self::step_sso($state);
case 'cleanup':
return self::step_cleanup($state);
default:
return [
'step' => $step,
'label' => get_string('error', 'meetletacbfree'),
'ok' => false,
'detail' => 'Unknown step',
'done' => true,
'abort' => true,
];
}
} catch (Throwable $e) {
$state['failed'] = true;
return [
'step' => $step,
'label' => get_string('error', 'meetletacbfree'),
'ok' => false,
'detail' => $e->getMessage(),
'done' => false,
'abort' => true,
];
}
}
/**
* Rebuild a fresh service (API client is not serializable in session).
*/
protected static function service(): service {
$service = new service();
$service->login_admin();
return $service;
}
protected static function step_login(array &$state): array {
$service = self::service();
$state['ok_login'] = true;
// Logout immediately; later steps re-login.
$service->logout();
return [
'step' => 'login',
'label' => get_string('testlogin', 'meetletacbfree'),
'ok' => true,
'detail' => '',
'done' => false,
'abort' => false,
];
}
protected static function step_folders(array &$state): array {
$service = self::service();
$content = $service->get_folder_scoid('content');
$archives = $service->get_folder_scoid('forced-archives');
$meetings = $service->get_folder_scoid('meetings');
$state['meetings'] = $meetings;
$ok = ($content && $archives && $meetings);
if (!$ok) {
$state['failed'] = true;
}
$service->logout();
return [
'step' => 'folders',
'label' => get_string('testfolders', 'meetletacbfree'),
'ok' => (bool)$ok,
'detail' => "content={$content} · archives={$archives} · meetings={$meetings}",
'done' => false,
'abort' => !$ok,
];
}
protected static function step_user(array &$state): array {
$service = self::service();
$meetings = (int)($state['meetings'] ?? 0);
if (!$meetings) {
$meetings = (int)$service->get_folder_scoid('meetings');
$state['meetings'] = $meetings;
}
$meeting = (object)[
'name' => 'meetlet_test_' . time(),
'starttime' => time(),
'endtime' => time() + HOURSECS,
'meeturl' => '',
'templatescoid' => 0,
];
$scoid = $service->create_meeting($meeting, $meetings);
$user = (object)[
'id' => random_int(900000000, 999999999),
'firstname' => 'MeetLet',
'lastname' => 'Test',
'username' => 'meetlettest' . random_int(1000, 9999),
'email' => 'meetlet.test.' . random_int(1000, 9999) . '@example.com',
];
$principal = $service->ensure_user($user);
$assigned = $service->assign_permission($principal->principalid, $scoid, service::ROLE_PRESENTER);
$state['scoid'] = $scoid;
$state['principalid'] = $principal->principalid;
$state['login'] = $principal->login;
$service->logout();
if (!$assigned) {
$state['failed'] = true;
}
return [
'step' => 'user',
'label' => get_string('testuser', 'meetletacbfree'),
'ok' => (bool)$assigned,
'detail' => '',
'done' => false,
'abort' => false,
];
}
protected static function step_sso(array &$state): array {
$directok = false;
$directdetail = '';
try {
$sso = new client();
$cookie = $sso->login_external(config::get_admin_login());
$directok = ($cookie !== '');
$directdetail = get_string('testsso_direct_ok', 'meetletacbfree');
} catch (Throwable $e) {
$msg = $e->getMessage();
$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', 'meetletacbfree');
} catch (Throwable $e) {
$directdetail .= ' · ' . get_string('testsso_userwarn', 'meetletacbfree');
}
}
if (!$directok) {
$state['failed'] = true;
}
return [
'step' => 'sso',
'label' => get_string('testsso', 'meetletacbfree'),
'ok' => $directok,
'detail' => $directdetail,
'done' => false,
'abort' => false,
];
}
protected static function step_cleanup(array &$state): array {
$service = self::service();
$client = $service->get_client();
$ok = true;
$detail = '';
try {
if (!empty($state['scoid'])) {
$service->delete_sco((int)$state['scoid']);
}
if (!empty($state['principalid'])) {
$client->request(['action' => 'principals-delete', 'principal-id' => (int)$state['principalid']]);
}
} catch (Throwable $e) {
$ok = false;
$detail = $e->getMessage();
}
$service->logout();
self::reset();
return [
'step' => 'cleanup',
'label' => get_string('testmeeting', 'meetletacbfree'),
'ok' => $ok,
'detail' => $detail,
'done' => true,
'abort' => false,
];
}
}