perf(modal): unify cancellable frontend modal flows
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+141
-27
@@ -11,6 +11,7 @@ use AKSRT\Identity\ApplicationRepository;
|
||||
use AKSRT\Identity\EvidenceService;
|
||||
use AKSRT\Identity\EventRepository;
|
||||
use AKSRT\Identity\TransitionService;
|
||||
use AKSRT\Identity\SettingsRuntime;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
@@ -44,49 +45,162 @@ class AuthApply {
|
||||
return is_array($types[$type] ?? null) ? $types[$type] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the current user's identity state from one repository context.
|
||||
*
|
||||
* The repository memoizes the latest/active/verified records for the
|
||||
* request, while this typed facade keeps all presentation callers on the
|
||||
* same application selection and next-action contract.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function snapshot(int $user_id): array {
|
||||
$user_id = absint($user_id);
|
||||
$settings = self::settings();
|
||||
$records = (new ApplicationRepository())->snapshot_for_user($user_id);
|
||||
$verified = is_array($records['verified'] ?? null) ? $records['verified'] : null;
|
||||
$latest = is_array($records['latest'] ?? null) ? $records['latest'] : null;
|
||||
$active = is_array($records['active'] ?? null) ? $records['active'] : null;
|
||||
$status_record = $verified ?: $latest;
|
||||
$status = $status_record
|
||||
? TransitionService::public_status((string) ($status_record['status'] ?? ''))
|
||||
: '';
|
||||
$current = $active ?: $latest;
|
||||
$stage = $active
|
||||
? (string) ($active['status'] ?? '')
|
||||
: (string) ($latest['status'] ?? '');
|
||||
$next_action = self::next_action($stage);
|
||||
$runtime_settings = class_exists('\\AKSRT\\Settings\\Settings') ? SettingsRuntime::get() : [];
|
||||
$poll_interval = max(5, (int) ($runtime_settings['poll_interval_seconds'] ?? 5));
|
||||
$can_apply = !empty($settings['enabled']) && !empty($settings['allow_apply']) && $status !== 'verified';
|
||||
|
||||
return [
|
||||
'user_id' => $user_id,
|
||||
'verified' => $verified !== null,
|
||||
'status' => $status,
|
||||
'stage' => $stage,
|
||||
'next_action' => $next_action,
|
||||
'poll_interval' => $poll_interval,
|
||||
'can_apply' => $can_apply,
|
||||
'latest' => $latest,
|
||||
'active' => $active,
|
||||
'current' => $current,
|
||||
'info' => $verified ? self::info_from_application($verified) : [],
|
||||
'apply' => self::payload_from_application($latest),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe browser-facing snapshot; raw application rows never cross this
|
||||
* boundary.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function snapshot_view(int $user_id): array {
|
||||
$snapshot = self::snapshot($user_id);
|
||||
$latest = is_array($snapshot['latest'] ?? null) ? $snapshot['latest'] : null;
|
||||
$active = is_array($snapshot['active'] ?? null) ? $snapshot['active'] : null;
|
||||
$current = is_array($snapshot['current'] ?? null) ? $snapshot['current'] : null;
|
||||
|
||||
return [
|
||||
'user_id' => (int) ($snapshot['user_id'] ?? 0),
|
||||
'verified' => !empty($snapshot['verified']),
|
||||
'status' => (string) ($snapshot['status'] ?? ''),
|
||||
'stage' => (string) ($snapshot['stage'] ?? ''),
|
||||
'next_action' => (string) ($snapshot['next_action'] ?? 'wait'),
|
||||
'poll_interval' => (int) ($snapshot['poll_interval'] ?? 5),
|
||||
'can_apply' => !empty($snapshot['can_apply']),
|
||||
'info' => is_array($snapshot['info'] ?? null) ? $snapshot['info'] : [],
|
||||
'current' => $current ? self::application_view_model($current, (int) ($snapshot['poll_interval'] ?? 5)) : null,
|
||||
'active' => $active ? self::application_view_model($active, (int) ($snapshot['poll_interval'] ?? 5)) : null,
|
||||
'latest' => $latest ? self::application_view_model($latest, (int) ($snapshot['poll_interval'] ?? 5)) : null,
|
||||
];
|
||||
}
|
||||
|
||||
private static function next_action(string $stage): string {
|
||||
if (in_array($stage, ['provider_pending', 'provider_processing'], true)) {
|
||||
return 'poll';
|
||||
}
|
||||
if (in_array($stage, ['provider_failed', 'provider_unsupported', 'provider_expired'], true)) {
|
||||
return 'manual_or_retry';
|
||||
}
|
||||
if ($stage === 'verified') {
|
||||
return 'complete';
|
||||
}
|
||||
return 'wait';
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private static function info_from_application(array $application): array {
|
||||
return [
|
||||
'name' => (string) ($application['public_name'] ?? ''),
|
||||
'desc' => (string) ($application['public_desc'] ?? ''),
|
||||
'type' => (string) ($application['type'] ?? ''),
|
||||
'time' => (string) (($application['completed_at'] ?? '') ?: ($application['updated_at'] ?? '')),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private static function payload_from_application(?array $application): array {
|
||||
if (!$application) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
'application_uuid' => (string) ($application['application_uuid'] ?? ''),
|
||||
'user_id' => (int) ($application['user_id'] ?? 0),
|
||||
'name' => (string) ($application['public_name'] ?? ''),
|
||||
'real_name' => (string) ($application['person_name_masked'] ?? ''),
|
||||
'desc' => (string) ($application['public_desc'] ?? ''),
|
||||
'msg' => (string) ($application['manual_reason'] ?? ''),
|
||||
'type' => (string) ($application['type'] ?? ''),
|
||||
'time' => (string) ($application['created_at'] ?? ''),
|
||||
'fee' => (float) ($application['fee_amount'] ?? 0),
|
||||
'_application' => $application,
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private static function application_view_model(array $application, int $poll_interval): array {
|
||||
$stage = (string) ($application['status'] ?? '');
|
||||
return [
|
||||
'uuid' => (string) ($application['application_uuid'] ?? ''),
|
||||
'type' => (string) ($application['type'] ?? ''),
|
||||
'status' => TransitionService::public_status($stage),
|
||||
'stage' => $stage,
|
||||
'next_action' => self::next_action($stage),
|
||||
'public_name' => (string) ($application['public_name'] ?? ''),
|
||||
'public_desc' => (string) ($application['public_desc'] ?? ''),
|
||||
'result_code' => (string) ($application['provider_result_code'] ?? ''),
|
||||
'message' => (string) ($application['provider_result_summary'] ?? ''),
|
||||
'redirect_url' => esc_url_raw((string) ($application['redirect_url'] ?? '')),
|
||||
'expires_at' => (string) ($application['expires_at'] ?? ''),
|
||||
'created_at' => (string) ($application['created_at'] ?? ''),
|
||||
'poll_interval' => $poll_interval,
|
||||
];
|
||||
}
|
||||
|
||||
public static function application_count(int $user_id, string $type): int {
|
||||
return (new ApplicationRepository())->count_user_type($user_id, sanitize_key($type));
|
||||
}
|
||||
|
||||
public static function get_status(int $user_id): string {
|
||||
$repo = new ApplicationRepository();
|
||||
$application = $repo->verified_for_user($user_id) ?: $repo->latest_for_user($user_id);
|
||||
return $application ? TransitionService::public_status((string) $application['status']) : '';
|
||||
return (string) (self::snapshot($user_id)['status'] ?? '');
|
||||
}
|
||||
|
||||
public static function is_verified(int $user_id): bool {
|
||||
return (new ApplicationRepository())->verified_for_user($user_id) !== null;
|
||||
return !empty(self::snapshot($user_id)['verified']);
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
public static function get_auth_info(int $user_id): array {
|
||||
$application = (new ApplicationRepository())->verified_for_user($user_id);
|
||||
return $application ? [
|
||||
'name' => (string) $application['public_name'],
|
||||
'desc' => (string) $application['public_desc'],
|
||||
'type' => (string) $application['type'],
|
||||
'time' => (string) ($application['completed_at'] ?: $application['updated_at']),
|
||||
] : [];
|
||||
$info = self::snapshot($user_id)['info'] ?? [];
|
||||
return is_array($info) ? $info : [];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
public static function get_apply_payload(int $user_id): array {
|
||||
$application = (new ApplicationRepository())->latest_for_user($user_id);
|
||||
if (!$application) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
'application_uuid' => (string) $application['application_uuid'],
|
||||
'user_id' => (int) $application['user_id'],
|
||||
'name' => (string) $application['public_name'],
|
||||
'real_name' => (string) $application['person_name_masked'],
|
||||
'desc' => (string) $application['public_desc'],
|
||||
'msg' => (string) ($application['manual_reason'] ?? ''),
|
||||
'type' => (string) $application['type'],
|
||||
'time' => (string) $application['created_at'],
|
||||
'fee' => (float) $application['fee_amount'],
|
||||
'_application' => $application,
|
||||
];
|
||||
$payload = self::snapshot($user_id)['apply'] ?? [];
|
||||
return is_array($payload) ? $payload : [];
|
||||
}
|
||||
|
||||
/** @return array<int,array{id:int,url:string,thumbnail_url:string}> */
|
||||
|
||||
Reference in New Issue
Block a user