feat(pages): 1:1 用户身份认证页 user-auth
Public apply/status shell on aksrt_user_verify_* meta, AJAX submit with materials upload, admin approve promotes apply payload to auth info.
This commit is contained in:
@@ -550,6 +550,18 @@ class UsersMenus {
|
||||
} elseif ($status === 'verified') {
|
||||
delete_user_meta($user_id, 'aksrt_user_verify_reason');
|
||||
}
|
||||
// Promote apply payload to public auth info when approved.
|
||||
if ($status === 'verified') {
|
||||
$apply = get_user_meta($user_id, 'aksrt_user_verify_apply', true);
|
||||
if (is_array($apply)) {
|
||||
update_user_meta($user_id, 'aksrt_user_verify_info', [
|
||||
'name' => (string) ($apply['name'] ?? ''),
|
||||
'desc' => (string) ($apply['desc'] ?? ''),
|
||||
'type' => (string) ($apply['type'] ?? ''),
|
||||
'time' => current_time('Y-m-d H:i'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
$log = get_option('aksrt_verify_review_log', []);
|
||||
$log = is_array($log) ? $log : [];
|
||||
$log[] = [
|
||||
|
||||
@@ -437,6 +437,29 @@ trait ScriptsPart1b {
|
||||
}
|
||||
}
|
||||
|
||||
// 用户身份认证页(zibll user-auth.php)
|
||||
if (is_page_template('templates/pages/page-user-auth.php')) {
|
||||
$ua_css = get_template_directory() . '/assets/css/routes/user-auth.css';
|
||||
if (file_exists($ua_css)) {
|
||||
wp_enqueue_style(
|
||||
'aksrt-route-user-auth',
|
||||
$base_uri . '/assets/css/routes/user-auth.css',
|
||||
['aksrt-tokens'],
|
||||
(string) filemtime($ua_css)
|
||||
);
|
||||
}
|
||||
$ua_js = get_template_directory() . '/assets/js/user-auth-page.js';
|
||||
if (file_exists($ua_js)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-user-auth-page',
|
||||
$base_uri . '/assets/js/user-auth-page.js',
|
||||
[],
|
||||
(string) filemtime($ua_js),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 交易中心共享壳层(购物车 / 订单 / 收益)
|
||||
$is_commerce_center = is_page_template('templates/pages/page-orders.php')
|
||||
|| is_page_template('templates/pages/page-cart.php')
|
||||
|
||||
@@ -47,6 +47,7 @@ class Templates {
|
||||
'templates/pages/page-posts-navs.php' => __('AKSRT - 文章导航', 'aksrt'),
|
||||
'templates/pages/page-friends.php' => __('AKSRT - 友情链接', 'aksrt'),
|
||||
'templates/pages/page-links.php' => __('AKSRT - 网址导航', 'aksrt'),
|
||||
'templates/pages/page-user-auth.php' => __('AKSRT - 用户身份认证', 'aksrt'),
|
||||
'templates/pages/page-orders.php' => __('AKSRT - 订单中心', 'aksrt'),
|
||||
'templates/pages/page-revenue.php' => __('AKSRT - 收益中心', 'aksrt'),
|
||||
'templates/pages/page-cart.php' => __('AKSRT - 购物车', 'aksrt'),
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
/**
|
||||
* Frontend identity verification apply (zibll user-auth page parity on aksrt_user_verify_* meta).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
namespace AKSRT\User;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class AuthApply {
|
||||
|
||||
public const STATUS_META = 'aksrt_user_verify_status';
|
||||
public const REASON_META = 'aksrt_user_verify_reason';
|
||||
public const APPLY_META = 'aksrt_user_verify_apply';
|
||||
public const INFO_META = 'aksrt_user_verify_info';
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function get_instance(): self {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function init(): void {
|
||||
add_action('wp_ajax_aksrt_user_auth_apply', [$this, 'ajax_apply']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{
|
||||
* enabled:bool,allow_apply:bool,public_display:bool,badge_text:string,
|
||||
* limit_level:int,desc:string,disable_desc:string,
|
||||
* types:array<int,array{slug:string,label:string}>
|
||||
* }
|
||||
*/
|
||||
public static function settings(): array {
|
||||
$all = class_exists('\AKSRT\Settings\Settings')
|
||||
? (array) \AKSRT\Settings\Settings::get_all()
|
||||
: [];
|
||||
$enabled = !isset($all['user_verify_enabled']) || !empty($all['user_verify_enabled']);
|
||||
$types_raw = (string) ($all['user_verify_apply_option'] ?? "real_name|实名认证\norganization|企业认证");
|
||||
$types = [];
|
||||
foreach (preg_split('/\r\n|\r|\n/', $types_raw) as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '') {
|
||||
continue;
|
||||
}
|
||||
$parts = array_map('trim', explode('|', $line, 2));
|
||||
$slug = sanitize_key($parts[0] ?? '');
|
||||
$label = $parts[1] ?? $parts[0];
|
||||
if ($slug === '') {
|
||||
continue;
|
||||
}
|
||||
$types[] = ['slug' => $slug, 'label' => (string) $label];
|
||||
}
|
||||
return [
|
||||
'enabled' => $enabled,
|
||||
'allow_apply' => !isset($all['user_verify_allow_apply']) || !empty($all['user_verify_allow_apply']),
|
||||
'public_display' => !isset($all['user_verify_public_display']) || !empty($all['user_verify_public_display']),
|
||||
'badge_text' => (string) ($all['user_verify_badge_text'] ?? __('已认证', 'aksrt')),
|
||||
'limit_level' => max(0, (int) ($all['user_verify_limit_level'] ?? 0)),
|
||||
'desc' => (string) ($all['user_verify_desc'] ?? ''),
|
||||
'disable_desc' => (string) ($all['user_verify_disable_desc'] ?? ''),
|
||||
'types' => $types,
|
||||
];
|
||||
}
|
||||
|
||||
public static function get_status(int $user_id): string {
|
||||
if ($user_id <= 0) {
|
||||
return '';
|
||||
}
|
||||
return sanitize_key((string) get_user_meta($user_id, self::STATUS_META, true));
|
||||
}
|
||||
|
||||
public static function is_verified(int $user_id): bool {
|
||||
return self::get_status($user_id) === 'verified';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function get_auth_info(int $user_id): array {
|
||||
$info = get_user_meta($user_id, self::INFO_META, true);
|
||||
return is_array($info) ? $info : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function get_apply_payload(int $user_id): array {
|
||||
$apply = get_user_meta($user_id, self::APPLY_META, true);
|
||||
return is_array($apply) ? $apply : [];
|
||||
}
|
||||
|
||||
public function ajax_apply(): void {
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('请先登录', 'aksrt')]);
|
||||
}
|
||||
if (!check_ajax_referer('aksrt_user_auth_apply', '_wpnonce', false)) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('安全校验失败', 'aksrt')]);
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$s = self::settings();
|
||||
if (!$s['enabled'] || !$s['allow_apply']) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('暂不能申请身份认证', 'aksrt')]);
|
||||
}
|
||||
if (self::is_verified($user_id)) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('您已是认证用户', 'aksrt')]);
|
||||
}
|
||||
if (self::get_status($user_id) === 'pending') {
|
||||
wp_send_json(['error' => 1, 'msg' => __('您的申请正在审核中', 'aksrt')]);
|
||||
}
|
||||
if ($s['limit_level'] > 0 && class_exists('\AKSRT\User\Level')) {
|
||||
$lv = (int) Level::get_level($user_id);
|
||||
if ($lv < $s['limit_level']) {
|
||||
wp_send_json([
|
||||
'error' => 1,
|
||||
'msg' => sprintf(
|
||||
/* translators: %d: required level */
|
||||
__('等级不足,需达到 LV.%d 后申请', 'aksrt'),
|
||||
$s['limit_level']
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$name = isset($_POST['name']) ? sanitize_text_field(wp_unslash((string) $_POST['name'])) : '';
|
||||
$desc = isset($_POST['desc']) ? sanitize_textarea_field(wp_unslash((string) $_POST['desc'])) : '';
|
||||
$msg = isset($_POST['msg']) ? sanitize_textarea_field(wp_unslash((string) $_POST['msg'])) : '';
|
||||
$type = isset($_POST['type']) ? sanitize_key((string) wp_unslash($_POST['type'])) : '';
|
||||
if ($name === '') {
|
||||
wp_send_json(['error' => 1, 'msg' => __('请填写认证身份名称', 'aksrt')]);
|
||||
}
|
||||
|
||||
$images = [];
|
||||
if (!empty($_FILES['image']['name'])) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
|
||||
$files = $_FILES['image'];
|
||||
// Normalize multi-file upload.
|
||||
$names = $files['name'];
|
||||
if (!is_array($names)) {
|
||||
$names = [$names];
|
||||
$tmp = [
|
||||
'name' => $names,
|
||||
'type' => [$files['type']],
|
||||
'tmp_name' => [$files['tmp_name']],
|
||||
'error' => [$files['error']],
|
||||
'size' => [$files['size']],
|
||||
];
|
||||
$files = $tmp;
|
||||
}
|
||||
$count = min(3, count($files['name']));
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (empty($files['name'][$i]) || (int) $files['error'][$i] !== UPLOAD_ERR_OK) {
|
||||
continue;
|
||||
}
|
||||
$file = [
|
||||
'name' => $files['name'][$i],
|
||||
'type' => $files['type'][$i],
|
||||
'tmp_name' => $files['tmp_name'][$i],
|
||||
'error' => $files['error'][$i],
|
||||
'size' => $files['size'][$i],
|
||||
];
|
||||
$_FILES['aksrt_auth_img'] = $file;
|
||||
$aid = media_handle_upload('aksrt_auth_img', 0);
|
||||
if (!is_wp_error($aid)) {
|
||||
$url = wp_get_attachment_url((int) $aid);
|
||||
if ($url) {
|
||||
$images[] = $url;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($_FILES['aksrt_auth_img']);
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'name' => $name,
|
||||
'desc' => $desc,
|
||||
'msg' => $msg,
|
||||
'type' => $type,
|
||||
'img' => $images,
|
||||
'time' => current_time('Y-m-d H:i'),
|
||||
];
|
||||
update_user_meta($user_id, self::APPLY_META, $payload);
|
||||
update_user_meta($user_id, self::STATUS_META, 'pending');
|
||||
delete_user_meta($user_id, self::REASON_META);
|
||||
|
||||
/**
|
||||
* @param int $user_id
|
||||
* @param array $payload
|
||||
*/
|
||||
do_action('aksrt_user_auth_apply_submitted', $user_id, $payload);
|
||||
|
||||
wp_send_json([
|
||||
'error' => 0,
|
||||
'msg' => __('提交成功,请等待管理员审核', 'aksrt'),
|
||||
'reload' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user