70 lines
3.1 KiB
PHP
70 lines
3.1 KiB
PHP
<?php
|
|
/**
|
|
* VIP membership event persistence.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Content;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
final class VipMembershipEventRepository {
|
|
|
|
private string $table;
|
|
|
|
public function __construct() {
|
|
$this->table = \AKSRT\Core\DBMigrator::table('vip_membership_event');
|
|
}
|
|
|
|
/** @param array<string,mixed> $event */
|
|
public function begin(array $event): string|\WP_Error {
|
|
global $wpdb;
|
|
if ($this->table === '') {
|
|
return new \WP_Error('aksrt_vip_audit_unavailable', __('会员变更审计表不可用。', 'aksrt'));
|
|
}
|
|
$uuid = wp_generate_uuid4();
|
|
$inserted = $wpdb->insert($this->table, [
|
|
'event_uuid' => $uuid,
|
|
'batch_uuid' => sanitize_text_field((string) ($event['batch_uuid'] ?? '')),
|
|
'user_id' => (int) ($event['user_id'] ?? 0),
|
|
'actor_user_id' => !empty($event['actor_user_id']) ? (int) $event['actor_user_id'] : null,
|
|
'operation' => sanitize_key((string) ($event['operation'] ?? '')),
|
|
'source' => sanitize_key((string) ($event['source'] ?? 'admin')),
|
|
'reason' => sanitize_text_field((string) ($event['reason'] ?? '')),
|
|
'request_json' => wp_json_encode((array) ($event['request'] ?? [])),
|
|
'before_json' => wp_json_encode((array) ($event['before'] ?? [])),
|
|
'status' => 'pending',
|
|
'created_at' => current_time('mysql', true),
|
|
]);
|
|
return $inserted === 1 ? $uuid : new \WP_Error('aksrt_vip_audit_begin_failed', __('无法创建会员变更审计记录。', 'aksrt'));
|
|
}
|
|
|
|
/** @param array<string,mixed> $after */
|
|
public function complete(string $uuid, string $status, array $after = [], string $error_code = '', string $error_message = ''): bool {
|
|
global $wpdb;
|
|
return $wpdb->update($this->table, [
|
|
'status' => in_array($status, ['succeeded', 'failed'], true) ? $status : 'failed',
|
|
'after_json' => wp_json_encode($after),
|
|
'error_code' => sanitize_key($error_code),
|
|
'error_message' => sanitize_text_field($error_message),
|
|
'completed_at' => current_time('mysql', true),
|
|
], ['event_uuid' => $uuid]) !== false;
|
|
}
|
|
|
|
/** @return array{items:array<int,array<string,mixed>>,total:int,pages:int} */
|
|
public function query(int $page, int $per_page): array {
|
|
global $wpdb;
|
|
if ($this->table === '') {
|
|
return ['items' => [], 'total' => 0, 'pages' => 1];
|
|
}
|
|
$total = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$this->table}");
|
|
$items = $wpdb->get_results($wpdb->prepare(
|
|
"SELECT e.*, u.display_name, u.user_login, a.display_name AS actor_name FROM {$this->table} e LEFT JOIN {$wpdb->users} u ON u.ID = e.user_id LEFT JOIN {$wpdb->users} a ON a.ID = e.actor_user_id ORDER BY e.id DESC LIMIT %d OFFSET %d",
|
|
$per_page,
|
|
max(0, $page - 1) * $per_page
|
|
), ARRAY_A);
|
|
return ['items' => is_array($items) ? $items : [], 'total' => $total, 'pages' => max(1, (int) ceil(max(1, $total) / $per_page))];
|
|
}
|
|
}
|