refactor: rename the theme brand and every identifier from AKSRT to Jio

Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-01 20:05:04 +08:00
1 parent 5b16bc6e15
commit 35bb96e82f
997 files changed
+28216 -28188

No files matched your search

+216 -216
View File
@@ -1,31 +1,31 @@
<?php
/**
* AKSRT 人机验证(Cloud Captcha)核心。
* Jio 人机验证(Cloud Captcha)核心。
*
* 唯一配置源:option `aksrt_captcha_config`。
* 唯一配置源:option `jio_captcha_config`。
* 闭环契约:
* aksrt_get_captcha_config() -> aksrt_is_captcha_enabled_for(scene)
* -> aksrt_render_captcha(scene) -> [data-aksrt-captcha-config] 挂载点
* -> captcha-front.js(public bundle)-> 客户端 AKSRTCaptcha + token
* -> 业务入口 aksrt_require_captcha(scene, $payload) -> proceed/fail。
* jio_get_captcha_config() -> jio_is_captcha_enabled_for(scene)
* -> jio_render_captcha(scene) -> [data-jio-captcha-config] 挂载点
* -> captcha-front.js(public bundle)-> 客户端 JioCaptcha + token
* -> 业务入口 jio_require_captcha(scene, $payload) -> proceed/fail。
*
* 仅支持云厂商:tencent / aliyun / cloudflare / geetest。
* 不含本地图形码 / 本地滑块。
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
const AKSRT_CAPTCHA_BROWSER_COOKIE = 'aksrt_captcha_browser';
const AKSRT_CAPTCHA_CHALLENGE_PREFIX = 'aksrt_captcha_challenge_';
const AKSRT_CAPTCHA_PROOF_PREFIX = 'aksrt_captcha_proof_';
const AKSRT_CAPTCHA_CHALLENGE_TTL = 10 * MINUTE_IN_SECONDS;
const AKSRT_CAPTCHA_PROOF_TTL = 5 * MINUTE_IN_SECONDS;
const JIO_CAPTCHA_BROWSER_COOKIE = 'jio_captcha_browser';
const JIO_CAPTCHA_CHALLENGE_PREFIX = 'jio_captcha_challenge_';
const JIO_CAPTCHA_PROOF_PREFIX = 'jio_captcha_proof_';
const JIO_CAPTCHA_CHALLENGE_TTL = 10 * MINUTE_IN_SECONDS;
const JIO_CAPTCHA_PROOF_TTL = 5 * MINUTE_IN_SECONDS;
function aksrt_captcha_browser_id(): string {
$value = isset($_COOKIE[AKSRT_CAPTCHA_BROWSER_COOKIE])
? sanitize_text_field(wp_unslash((string) $_COOKIE[AKSRT_CAPTCHA_BROWSER_COOKIE]))
function jio_captcha_browser_id(): string {
$value = isset($_COOKIE[JIO_CAPTCHA_BROWSER_COOKIE])
? sanitize_text_field(wp_unslash((string) $_COOKIE[JIO_CAPTCHA_BROWSER_COOKIE]))
: '';
if (preg_match('/^[A-Za-z0-9_-]{32,80}$/', $value) === 1) {
return $value;
@@ -33,7 +33,7 @@ function aksrt_captcha_browser_id(): string {
$value = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
if (!headers_sent()) {
setcookie(AKSRT_CAPTCHA_BROWSER_COOKIE, $value, [
setcookie(JIO_CAPTCHA_BROWSER_COOKIE, $value, [
'expires' => time() + MONTH_IN_SECONDS,
'path' => defined('COOKIEPATH') && COOKIEPATH ? COOKIEPATH : '/',
'domain' => defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '',
@@ -42,29 +42,29 @@ function aksrt_captcha_browser_id(): string {
'samesite' => 'Lax',
]);
}
$_COOKIE[AKSRT_CAPTCHA_BROWSER_COOKIE] = $value;
$_COOKIE[JIO_CAPTCHA_BROWSER_COOKIE] = $value;
return $value;
}
function aksrt_captcha_challenge_key(string $token): string {
return AKSRT_CAPTCHA_CHALLENGE_PREFIX . hash('sha256', trim($token));
function jio_captcha_challenge_key(string $token): string {
return JIO_CAPTCHA_CHALLENGE_PREFIX . hash('sha256', trim($token));
}
function aksrt_captcha_challenge_material(string $scene, string $provider, string $nonce, int $timestamp): string {
function jio_captcha_challenge_material(string $scene, string $provider, string $nonce, int $timestamp): string {
$host = strtolower((string) wp_parse_url(home_url('/'), PHP_URL_HOST));
return sanitize_key($scene) . '|' . sanitize_key($provider) . '|'
. hash('sha256', aksrt_captcha_browser_id()) . '|' . $host . '|' . $timestamp . '|' . $nonce;
. hash('sha256', jio_captcha_browser_id()) . '|' . $host . '|' . $timestamp . '|' . $nonce;
}
function aksrt_captcha_issue_challenge(string $scene, string $provider): string {
function jio_captcha_issue_challenge(string $scene, string $provider): string {
$nonce = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
$timestamp = time();
$material = aksrt_captcha_challenge_material($scene, $provider, $nonce, $timestamp);
$material = jio_captcha_challenge_material($scene, $provider, $nonce, $timestamp);
$signature = hash_hmac('sha256', $material, wp_salt('auth'));
return $nonce . '.' . $timestamp . '.' . $signature;
}
function aksrt_captcha_challenge_valid(string $token, string $scene, string $provider): bool {
function jio_captcha_challenge_valid(string $token, string $scene, string $provider): bool {
$parts = explode('.', trim($token));
if (count($parts) !== 3) {
return false;
@@ -74,22 +74,22 @@ function aksrt_captcha_challenge_valid(string $token, string $scene, string $pro
return false;
}
$timestamp = (int) $raw_timestamp;
if ($timestamp > time() + 60 || $timestamp < time() - AKSRT_CAPTCHA_CHALLENGE_TTL) {
if ($timestamp > time() + 60 || $timestamp < time() - JIO_CAPTCHA_CHALLENGE_TTL) {
return false;
}
$expected = hash_hmac(
'sha256',
aksrt_captcha_challenge_material($scene, $provider, $nonce, $timestamp),
jio_captcha_challenge_material($scene, $provider, $nonce, $timestamp),
wp_salt('auth')
);
return hash_equals($expected, $signature);
}
function aksrt_captcha_validate_challenge(string $token, string $scene, string $provider, bool $claim = false): bool {
if (!aksrt_captcha_challenge_valid($token, $scene, $provider)) {
function jio_captcha_validate_challenge(string $token, string $scene, string $provider, bool $claim = false): bool {
if (!jio_captcha_challenge_valid($token, $scene, $provider)) {
return false;
}
$key = aksrt_captcha_challenge_key($token);
$key = jio_captcha_challenge_key($token);
if (!$claim) {
$current = get_option($key, null);
if (is_numeric($current) && (int) $current < time()) {
@@ -103,15 +103,15 @@ function aksrt_captcha_validate_challenge(string $token, string $scene, string $
if (is_numeric($current) && (int) $current < time()) {
delete_option($key);
}
return add_option($key, time() + AKSRT_CAPTCHA_CHALLENGE_TTL, '', false);
return add_option($key, time() + JIO_CAPTCHA_CHALLENGE_TTL, '', false);
}
function aksrt_captcha_challenge_release(string $token): void {
delete_option(aksrt_captcha_challenge_key($token));
function jio_captcha_challenge_release(string $token): void {
delete_option(jio_captcha_challenge_key($token));
}
function aksrt_captcha_rate_limited(string $scope, string $subject, int $limit = 30, int $ttl = 60): bool {
$key = 'aksrt_captcha_rl_' . md5($scope . '|' . strtolower($subject));
function jio_captcha_rate_limited(string $scope, string $subject, int $limit = 30, int $ttl = 60): bool {
$key = 'jio_captcha_rl_' . md5($scope . '|' . strtolower($subject));
$count = (int) get_transient($key);
if ($count >= $limit) {
return true;
@@ -120,37 +120,37 @@ function aksrt_captcha_rate_limited(string $scope, string $subject, int $limit =
return false;
}
function aksrt_captcha_proof_key(string $token): string {
return AKSRT_CAPTCHA_PROOF_PREFIX . hash('sha256', trim($token));
function jio_captcha_proof_key(string $token): string {
return JIO_CAPTCHA_PROOF_PREFIX . hash('sha256', trim($token));
}
function aksrt_captcha_issue_proof(string $scene, string $provider): string {
function jio_captcha_issue_proof(string $scene, string $provider): string {
$token = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
$row = [
'scene' => sanitize_key($scene),
'provider' => sanitize_key($provider),
'browser_hash' => hash('sha256', aksrt_captcha_browser_id()),
'browser_hash' => hash('sha256', jio_captcha_browser_id()),
'host' => strtolower((string) wp_parse_url(home_url('/'), PHP_URL_HOST)),
'expires_at' => time() + AKSRT_CAPTCHA_PROOF_TTL,
'expires_at' => time() + JIO_CAPTCHA_PROOF_TTL,
];
if (!add_option(aksrt_captcha_proof_key($token), $row, '', false)) {
if (!add_option(jio_captcha_proof_key($token), $row, '', false)) {
throw new \RuntimeException('captcha_proof_issue_failed');
}
return $token;
}
function aksrt_captcha_consume_proof(string $token, string $scene, string $provider): bool {
function jio_captcha_consume_proof(string $token, string $scene, string $provider): bool {
if ($token === '') {
return false;
}
$key = aksrt_captcha_proof_key($token);
$key = jio_captcha_proof_key($token);
$row = get_option($key, null);
$host = strtolower((string) wp_parse_url(home_url('/'), PHP_URL_HOST));
$valid = is_array($row)
&& (int) ($row['expires_at'] ?? 0) >= time()
&& hash_equals(sanitize_key($scene), (string) ($row['scene'] ?? ''))
&& hash_equals(sanitize_key($provider), (string) ($row['provider'] ?? ''))
&& hash_equals(hash('sha256', aksrt_captcha_browser_id()), (string) ($row['browser_hash'] ?? ''))
&& hash_equals(hash('sha256', jio_captcha_browser_id()), (string) ($row['browser_hash'] ?? ''))
&& $host !== ''
&& hash_equals($host, (string) ($row['host'] ?? ''));
if (!$valid) {
@@ -173,9 +173,9 @@ function aksrt_captcha_consume_proof(string $token, string $scene, string $provi
return true;
}
function aksrt_captcha_cleanup_records(int $limit = 200): int {
function jio_captcha_cleanup_records(int $limit = 200): int {
global $wpdb;
$prefixes = [AKSRT_CAPTCHA_CHALLENGE_PREFIX, AKSRT_CAPTCHA_PROOF_PREFIX];
$prefixes = [JIO_CAPTCHA_CHALLENGE_PREFIX, JIO_CAPTCHA_PROOF_PREFIX];
$removed = 0;
foreach ($prefixes as $prefix) {
$rows = $wpdb->get_results($wpdb->prepare(
@@ -196,68 +196,68 @@ function aksrt_captcha_cleanup_records(int $limit = 200): int {
add_action('init', static function (): void {
if (wp_rand(1, 100) === 1) {
aksrt_captcha_cleanup_records();
jio_captcha_cleanup_records();
}
}, 30);
add_action('rest_api_init', static function (): void {
register_rest_route('aksrt/v1', '/captcha/challenge', [
register_rest_route('jio/v1', '/captcha/challenge', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => static function (\WP_REST_Request $request) {
$data = $request->get_json_params();
$scene = sanitize_key((string) (is_array($data) ? ($data['scene'] ?? '') : ''));
if (!aksrt_is_captcha_enabled_for($scene)) {
return new \WP_Error('aksrt_captcha_scene', __('人机验证场景未启用', 'aksrt'), ['status' => 400]);
if (!jio_is_captcha_enabled_for($scene)) {
return new \WP_Error('jio_captcha_scene', __('人机验证场景未启用', 'jio'), ['status' => 400]);
}
$cfg = aksrt_get_captcha_config();
$cfg = jio_get_captcha_config();
$provider = $cfg['active_provider'];
if ($provider === '' || !aksrt_captcha_provider_is_configured($provider, $cfg[$provider] ?? [])) {
return new \WP_Error('aksrt_captcha_config', __('人机验证配置不完整', 'aksrt'), ['status' => 503]);
if ($provider === '' || !jio_captcha_provider_is_configured($provider, $cfg[$provider] ?? [])) {
return new \WP_Error('jio_captcha_config', __('人机验证配置不完整', 'jio'), ['status' => 503]);
}
if (aksrt_captcha_rate_limited('challenge:' . $scene, aksrt_get_client_ip(), 20, MINUTE_IN_SECONDS)) {
return new \WP_Error('aksrt_captcha_rate', __('请求过于频繁,请稍后再试', 'aksrt'), ['status' => 429]);
if (jio_captcha_rate_limited('challenge:' . $scene, jio_get_client_ip(), 20, MINUTE_IN_SECONDS)) {
return new \WP_Error('jio_captcha_rate', __('请求过于频繁,请稍后再试', 'jio'), ['status' => 429]);
}
return new \WP_REST_Response([
'success' => true,
'data' => ['challenge' => aksrt_captcha_issue_challenge($scene, $provider)],
'data' => ['challenge' => jio_captcha_issue_challenge($scene, $provider)],
], 200);
},
]);
register_rest_route('aksrt/v1', '/captcha/exchange', [
register_rest_route('jio/v1', '/captcha/exchange', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => static function (\WP_REST_Request $request) {
$data = $request->get_json_params();
$data = is_array($data) ? $data : [];
$scene = sanitize_key((string) ($data['scene'] ?? ''));
if (!aksrt_is_captcha_enabled_for($scene)) {
return new \WP_Error('aksrt_captcha_scene', __('人机验证场景未启用', 'aksrt'), ['status' => 400]);
if (!jio_is_captcha_enabled_for($scene)) {
return new \WP_Error('jio_captcha_scene', __('人机验证场景未启用', 'jio'), ['status' => 400]);
}
$cfg = aksrt_get_captcha_config();
$cfg = jio_get_captcha_config();
$provider = $cfg['active_provider'];
$pcfg = $cfg[$provider] ?? [];
if ($provider === '' || !aksrt_captcha_provider_is_configured($provider, $pcfg)) {
return new \WP_Error('aksrt_captcha_config', __('人机验证配置不完整', 'aksrt'), ['status' => 503]);
if ($provider === '' || !jio_captcha_provider_is_configured($provider, $pcfg)) {
return new \WP_Error('jio_captcha_config', __('人机验证配置不完整', 'jio'), ['status' => 503]);
}
$challenge = sanitize_text_field((string) ($data['aksrt_captcha_challenge'] ?? ''));
if (!aksrt_captcha_validate_challenge($challenge, $scene, $provider, false)) {
return new \WP_Error('aksrt_captcha_challenge', __('人机验证会话无效或已过期,请重试', 'aksrt'), ['status' => 400]);
$challenge = sanitize_text_field((string) ($data['jio_captcha_challenge'] ?? ''));
if (!jio_captcha_validate_challenge($challenge, $scene, $provider, false)) {
return new \WP_Error('jio_captcha_challenge', __('人机验证会话无效或已过期,请重试', 'jio'), ['status' => 400]);
}
// 原子占用 challenge:并发请求只有首个能进入厂商验签,其余直接 409,避免同一票据放大厂商调用。
if (!aksrt_captcha_validate_challenge($challenge, $scene, $provider, true)) {
return new \WP_Error('aksrt_captcha_replayed', __('人机验证会话已在验证中,请重试', 'aksrt'), ['status' => 409]);
if (!jio_captcha_validate_challenge($challenge, $scene, $provider, true)) {
return new \WP_Error('jio_captcha_replayed', __('人机验证会话已在验证中,请重试', 'jio'), ['status' => 409]);
}
$result = aksrt_verify_captcha_provider($provider, $pcfg, $data, aksrt_get_client_ip(), $scene);
$result = jio_verify_captcha_provider($provider, $pcfg, $data, jio_get_client_ip(), $scene);
if (is_wp_error($result)) {
aksrt_captcha_challenge_release($challenge);
jio_captcha_challenge_release($challenge);
return $result;
}
try {
$proof = aksrt_captcha_issue_proof($scene, $provider);
$proof = jio_captcha_issue_proof($scene, $provider);
} catch (\Throwable $e) {
aksrt_captcha_challenge_release($challenge);
return new \WP_Error('aksrt_captcha_proof', __('无法创建人机验证凭证,请重试', 'aksrt'), ['status' => 500]);
jio_captcha_challenge_release($challenge);
return new \WP_Error('jio_captcha_proof', __('无法创建人机验证凭证,请重试', 'jio'), ['status' => 500]);
}
return new \WP_REST_Response([
'success' => true,
@@ -267,10 +267,10 @@ add_action('rest_api_init', static function (): void {
]);
});
function aksrt_captcha_provider_metadata(): array {
function jio_captcha_provider_metadata(): array {
return [
'tencent' => [
'label' => __('腾讯云 Captcha', 'aksrt'),
'label' => __('腾讯云 Captcha', 'jio'),
'fields' => [
'secret_id' => ['default' => '', 'required' => true],
'secret_key' => ['default' => '', 'required' => true, 'secret' => true],
@@ -279,7 +279,7 @@ function aksrt_captcha_provider_metadata(): array {
],
],
'aliyun' => [
'label' => __('阿里云 CAPTCHA 2.0', 'aksrt'),
'label' => __('阿里云 CAPTCHA 2.0', 'jio'),
'fields' => [
'region' => ['default' => 'cn', 'required' => true, 'values' => ['cn', 'sgp']],
'prefix' => ['default' => '', 'required' => true],
@@ -289,7 +289,7 @@ function aksrt_captcha_provider_metadata(): array {
],
],
'cloudflare' => [
'label' => __('Cloudflare Turnstile', 'aksrt'),
'label' => __('Cloudflare Turnstile', 'jio'),
'fields' => [
'site_key' => ['default' => '', 'required' => true],
'secret_key' => ['default' => '', 'required' => true, 'secret' => true],
@@ -298,7 +298,7 @@ function aksrt_captcha_provider_metadata(): array {
],
],
'geetest' => [
'label' => __('极验 GeeTest', 'aksrt'),
'label' => __('极验 GeeTest', 'jio'),
'fields' => [
'captcha_id' => ['default' => '', 'required' => true],
'captcha_key' => ['default' => '', 'required' => true, 'secret' => true],
@@ -311,15 +311,15 @@ function aksrt_captcha_provider_metadata(): array {
/**
* 支持的验证服务商。
*/
function aksrt_captcha_providers(): array {
return array_keys(aksrt_captcha_provider_metadata());
function jio_captcha_providers(): array {
return array_keys(jio_captcha_provider_metadata());
}
/**
* 服务商字段白名单与默认值。
*/
function aksrt_captcha_provider_defaults(string $provider): array {
$fields = aksrt_captcha_provider_metadata()[$provider]['fields'] ?? [];
function jio_captcha_provider_defaults(string $provider): array {
$fields = jio_captcha_provider_metadata()[$provider]['fields'] ?? [];
$defaults = [];
foreach ($fields as $key => $meta) {
$defaults[$key] = $meta['default'] ?? '';
@@ -330,21 +330,21 @@ function aksrt_captcha_provider_defaults(string $provider): array {
/**
* 服务商 secret 字段。
*/
function aksrt_captcha_provider_secret_fields(string $provider): array {
$fields = aksrt_captcha_provider_metadata()[$provider]['fields'] ?? [];
function jio_captcha_provider_secret_fields(string $provider): array {
$fields = jio_captcha_provider_metadata()[$provider]['fields'] ?? [];
return array_values(array_keys(array_filter($fields, static fn(array $meta): bool => !empty($meta['secret']))));
}
/**
* 按集中元数据规范化服务商配置,丢弃未知键。
*/
function aksrt_captcha_sanitize_provider_config(string $provider, $raw): array {
$meta = aksrt_captcha_provider_metadata()[$provider]['fields'] ?? [];
function jio_captcha_sanitize_provider_config(string $provider, $raw): array {
$meta = jio_captcha_provider_metadata()[$provider]['fields'] ?? [];
if ($meta === []) {
return [];
}
$raw = is_array($raw) ? $raw : [];
$clean = aksrt_captcha_provider_defaults($provider);
$clean = jio_captcha_provider_defaults($provider);
foreach ($meta as $key => $field) {
if (!array_key_exists($key, $raw) || is_array($raw[$key]) || is_object($raw[$key])) {
continue;
@@ -361,36 +361,36 @@ function aksrt_captcha_sanitize_provider_config(string $provider, $raw): array {
/**
* 人机验证场景白名单。
*/
function aksrt_captcha_scenes(): array {
function jio_captcha_scenes(): array {
return [
'comment' => __('发表评论', 'aksrt'),
'login' => __('用户登录', 'aksrt'),
'register' => __('用户注册', 'aksrt'),
'bind' => __('绑定第三方', 'aksrt'),
'bind_phone' => __('绑定手机', 'aksrt'),
'lostpassword' => __('找回密码', 'aksrt'),
'change_password' => __('修改密码', 'aksrt'),
'change_email' => __('更改邮箱', 'aksrt'),
'download' => __('资源下载', 'aksrt'),
'signin' => __('每日签到', 'aksrt'),
'front_submit' => __('前台投稿', 'aksrt'),
'tip_user' => __('打赏用户', 'aksrt'),
'ticket_create' => __('提交工单', 'aksrt'),
'ticket_reply' => __('回复工单', 'aksrt'),
'comment' => __('发表评论', 'jio'),
'login' => __('用户登录', 'jio'),
'register' => __('用户注册', 'jio'),
'bind' => __('绑定第三方', 'jio'),
'bind_phone' => __('绑定手机', 'jio'),
'lostpassword' => __('找回密码', 'jio'),
'change_password' => __('修改密码', 'jio'),
'change_email' => __('更改邮箱', 'jio'),
'download' => __('资源下载', 'jio'),
'signin' => __('每日签到', 'jio'),
'front_submit' => __('前台投稿', 'jio'),
'tip_user' => __('打赏用户', 'jio'),
'ticket_create' => __('提交工单', 'jio'),
'ticket_reply' => __('回复工单', 'jio'),
];
}
/**
* 默认配置结构。
*/
function aksrt_captcha_default_config(): array {
function jio_captcha_default_config(): array {
$config = [
'enabled' => false,
'active_provider' => '',
'enabled_scenarios' => [],
];
foreach (aksrt_captcha_providers() as $provider) {
$config[$provider] = aksrt_captcha_provider_defaults($provider);
foreach (jio_captcha_providers() as $provider) {
$config[$provider] = jio_captcha_provider_defaults($provider);
}
return $config;
}
@@ -401,12 +401,12 @@ function aksrt_captcha_default_config(): array {
* @param mixed $raw
* @return array<int, string>
*/
function aksrt_captcha_sanitize_scene_list($raw): array {
function jio_captcha_sanitize_scene_list($raw): array {
$list = is_array($raw) ? $raw : [];
$clean = [];
foreach ($list as $scene) {
$scene = sanitize_key((string) $scene);
if ($scene !== '' && array_key_exists($scene, aksrt_captcha_scenes()) && !in_array($scene, $clean, true)) {
if ($scene !== '' && array_key_exists($scene, jio_captcha_scenes()) && !in_array($scene, $clean, true)) {
$clean[] = $scene;
}
}
@@ -416,33 +416,33 @@ function aksrt_captcha_sanitize_scene_list($raw): array {
/**
* 获取人机验证完整配置(规范化,不合并历史脏键)。
*
* 结果在同一请求内缓存;后台保存后调用 aksrt_captcha_config_reset() 失效。
* 结果在同一请求内缓存;后台保存后调用 jio_captcha_config_reset() 失效。
*
* @return array
*/
function aksrt_get_captcha_config(): array {
$cache =& $GLOBALS['aksrt_captcha_config_cache'];
function jio_get_captcha_config(): array {
$cache =& $GLOBALS['jio_captcha_config_cache'];
if (is_array($cache)) {
return $cache;
}
$stored = get_option('aksrt_captcha_config', []);
$cfg = array_merge(aksrt_captcha_default_config(), is_array($stored) ? $stored : []);
$stored = get_option('jio_captcha_config', []);
$cfg = array_merge(jio_captcha_default_config(), is_array($stored) ? $stored : []);
$provider = isset($cfg['active_provider']) ? sanitize_key((string) $cfg['active_provider']) : '';
if (!in_array($provider, aksrt_captcha_providers(), true)) {
if (!in_array($provider, jio_captcha_providers(), true)) {
$provider = '';
}
$enabled = aksrt_captcha_sanitize_scene_list($cfg['enabled_scenarios'] ?? []);
$enabled = jio_captcha_sanitize_scene_list($cfg['enabled_scenarios'] ?? []);
$result = [
'enabled' => !empty($cfg['enabled']),
'active_provider' => $provider,
'enabled_scenarios' => $enabled,
];
foreach (aksrt_captcha_providers() as $p) {
$result[$p] = aksrt_captcha_sanitize_provider_config($p, $cfg[$p] ?? []);
foreach (jio_captcha_providers() as $p) {
$result[$p] = jio_captcha_sanitize_provider_config($p, $cfg[$p] ?? []);
}
$cache = $result;
@@ -452,26 +452,26 @@ function aksrt_get_captcha_config(): array {
/**
* 使请求内的配置缓存失效(后台保存路径调用)。
*/
function aksrt_captcha_config_reset(): void {
$GLOBALS['aksrt_captcha_config_cache'] = null;
function jio_captcha_config_reset(): void {
$GLOBALS['jio_captcha_config_cache'] = null;
}
/**
* 各服务商必填字段。
*/
function aksrt_captcha_required_fields(string $provider): array {
$fields = aksrt_captcha_provider_metadata()[$provider]['fields'] ?? [];
function jio_captcha_required_fields(string $provider): array {
$fields = jio_captcha_provider_metadata()[$provider]['fields'] ?? [];
return array_values(array_keys(array_filter($fields, static fn(array $meta): bool => !empty($meta['required']))));
}
/**
* 当前服务商必填凭据是否齐全(避免空 captcha_id 打到第三方 403)。
*/
function aksrt_captcha_provider_is_configured(string $provider, array $pcfg = []): bool {
if (!in_array($provider, aksrt_captcha_providers(), true)) {
function jio_captcha_provider_is_configured(string $provider, array $pcfg = []): bool {
if (!in_array($provider, jio_captcha_providers(), true)) {
return false;
}
$required = aksrt_captcha_required_fields($provider);
$required = jio_captcha_required_fields($provider);
if (empty($required)) {
return false;
}
@@ -486,16 +486,16 @@ function aksrt_captcha_provider_is_configured(string $provider, array $pcfg = []
/**
* 指定场景是否启用人机验证。
*
* @param string $scene 见 aksrt_captcha_scenes()
* @param string $scene 见 jio_captcha_scenes()
* @return bool
*/
function aksrt_is_captcha_enabled_for($scene): bool {
function jio_is_captcha_enabled_for($scene): bool {
$scene = sanitize_key((string) $scene);
if (!array_key_exists($scene, aksrt_captcha_scenes())) {
if (!array_key_exists($scene, jio_captcha_scenes())) {
return false;
}
$cfg = aksrt_get_captcha_config();
$cfg = jio_get_captcha_config();
if (empty($cfg['enabled'])) {
return false;
}
@@ -510,20 +510,20 @@ function aksrt_is_captcha_enabled_for($scene): bool {
* @param array $payload 客户端提交的验证字段
* @return true|\WP_Error 成功返回 true,失败返回 WP_Error
*/
function aksrt_require_captcha(string $scene, array $payload = []) {
if (!aksrt_is_captcha_enabled_for($scene)) {
function jio_require_captcha(string $scene, array $payload = []) {
if (!jio_is_captcha_enabled_for($scene)) {
return true;
}
$cfg = aksrt_get_captcha_config();
$cfg = jio_get_captcha_config();
$provider = $cfg['active_provider'];
if ($provider === '' || !aksrt_captcha_provider_is_configured($provider, $cfg[$provider] ?? [])) {
return aksrt_captcha_error('aksrt_captcha_config', __('人机验证配置不完整,请联系站点管理员', 'aksrt'));
if ($provider === '' || !jio_captcha_provider_is_configured($provider, $cfg[$provider] ?? [])) {
return jio_captcha_error('jio_captcha_config', __('人机验证配置不完整,请联系站点管理员', 'jio'));
}
$proof = sanitize_text_field((string) ($payload['aksrt_captcha_proof'] ?? ''));
if (!aksrt_captcha_consume_proof($proof, $scene, $provider)) {
return aksrt_captcha_error('aksrt_captcha_proof', __('人机验证凭证无效、已过期或已使用,请重试', 'aksrt'));
$proof = sanitize_text_field((string) ($payload['jio_captcha_proof'] ?? ''));
if (!jio_captcha_consume_proof($proof, $scene, $provider)) {
return jio_captcha_error('jio_captcha_proof', __('人机验证凭证无效、已过期或已使用,请重试', 'jio'));
}
return true;
}
@@ -531,17 +531,17 @@ function aksrt_require_captcha(string $scene, array $payload = []) {
/**
* 后台摘要:enabled / provider / configured / 场景命中状态。
*/
function aksrt_get_captcha_status_summary(): array {
$cfg = aksrt_get_captcha_config();
function jio_get_captcha_status_summary(): array {
$cfg = jio_get_captcha_config();
$provider = $cfg['active_provider'];
$scenes = [];
foreach (aksrt_captcha_scenes() as $key => $label) {
$scenes[$key] = aksrt_is_captcha_enabled_for($key);
foreach (jio_captcha_scenes() as $key => $label) {
$scenes[$key] = jio_is_captcha_enabled_for($key);
}
return [
'enabled' => !empty($cfg['enabled']),
'provider' => $provider,
'configured' => $provider !== '' && aksrt_captcha_provider_is_configured($provider, $cfg[$provider] ?? []),
'configured' => $provider !== '' && jio_captcha_provider_is_configured($provider, $cfg[$provider] ?? []),
'scenes' => $scenes,
];
}
@@ -553,17 +553,17 @@ add_action('admin_notices', static function () {
if (!current_user_can('manage_options')) {
return;
}
$cfg = aksrt_get_captcha_config();
$cfg = jio_get_captcha_config();
if (empty($cfg['enabled']) || $cfg['active_provider'] === '') {
return;
}
$provider = $cfg['active_provider'];
if (aksrt_captcha_provider_is_configured($provider, $cfg[$provider] ?? [])) {
if (jio_captcha_provider_is_configured($provider, $cfg[$provider] ?? [])) {
return;
}
echo '<div class="notice notice-error"><p>' . esc_html(sprintf(
/* translators: %s: captcha provider key */
__('人机验证服务商「%s」已启用但凭据未配齐,已启用场景将拒绝请求。请到「功能&权限 → 人机验证」补全配置。', 'aksrt'),
__('人机验证服务商「%s」已启用但凭据未配齐,已启用场景将拒绝请求。请到「功能&权限 → 人机验证」补全配置。', 'jio'),
$provider
)) . '</p></div>';
});
@@ -572,13 +572,13 @@ add_action('admin_notices', static function () {
// 客户端真实 IP(穿透 CDN / 代理)
// ============================================================
function aksrt_get_client_ip(): string {
function jio_get_client_ip(): string {
$remote = isset($_SERVER['REMOTE_ADDR']) ? (string) $_SERVER['REMOTE_ADDR'] : '';
// 信任代理名单:过滤返回非空 CIDR/IP 列表时,仅当 REMOTE_ADDR 命中名单
// 才采纳 CDN / 反代头;否则客户端可伪造这些头绕过 IP 维度的风控。
$trusted = apply_filters('aksrt_trusted_proxies', []);
if (is_array($trusted) && $trusted !== [] && $remote !== '' && !aksrt_ip_in_list($remote, $trusted)) {
$trusted = apply_filters('jio_trusted_proxies', []);
if (is_array($trusted) && $trusted !== [] && $remote !== '' && !jio_ip_in_list($remote, $trusted)) {
return $remote;
}
@@ -619,7 +619,7 @@ function aksrt_get_client_ip(): string {
* @param string $ip 待判定 IP。
* @param array $list 精确 IP / CIDR 段列表。
*/
function aksrt_ip_in_list(string $ip, array $list): bool {
function jio_ip_in_list(string $ip, array $list): bool {
foreach ($list as $entry) {
$entry = trim((string) $entry);
if ($entry === '') {
@@ -659,9 +659,9 @@ function aksrt_ip_in_list(string $ip, array $list): bool {
}
// Native wp-comments-post + any path that omits comment_author_IP.
// Ensures comment_author_IP (and thus aksrt_comment_addr) is the real client IP behind CDN.
// Ensures comment_author_IP (and thus jio_comment_addr) is the real client IP behind CDN.
add_filter('pre_comment_user_ip', static function ($ip) {
$resolved = aksrt_get_client_ip();
$resolved = jio_get_client_ip();
return ($resolved !== '' && $resolved !== '0.0.0.0') ? $resolved : $ip;
}, 5);
@@ -669,7 +669,7 @@ add_filter('pre_comment_user_ip', static function ($ip) {
// 腾讯云 API 3.0 TC3-HMAC-SHA256 签名
// ============================================================
function aksrt_tencent_tc3_sign($secret_id, $secret_key, $service, $timestamp, $date, $action, $version, $payload): array {
function jio_tencent_tc3_sign($secret_id, $secret_key, $service, $timestamp, $date, $action, $version, $payload): array {
$content_type = 'application/json; charset=utf-8';
$host = 'captcha.tencentcloudapi.com';
$payload_hash = hash('sha256', $payload);
@@ -703,7 +703,7 @@ function aksrt_tencent_tc3_sign($secret_id, $secret_key, $service, $timestamp, $
/**
* 阿里云 OpenAPI POP Signature v1.0 (HMAC-SHA1)。
*/
function aksrt_aliyun_afs_sign(array $params, string $secret): string {
function jio_aliyun_afs_sign(array $params, string $secret): string {
ksort($params);
$canonicalized = '';
foreach ($params as $k => $v) {
@@ -720,11 +720,11 @@ function aksrt_aliyun_afs_sign(array $params, string $secret): string {
/**
* 记录传输层 / 厂商原始错误细节,供站点排查;对用户只暴露通用文案。
*/
function aksrt_captcha_log(string $provider, string $detail): void {
error_log('[AKSRT Captcha] ' . $provider . ': ' . $detail);
function jio_captcha_log(string $provider, string $detail): void {
error_log('[Jio Captcha] ' . $provider . ': ' . $detail);
}
function aksrt_captcha_error(string $code, string $message, array $data = []): \WP_Error {
function jio_captcha_error(string $code, string $message, array $data = []): \WP_Error {
return new \WP_Error($code, $message, $data);
}
@@ -733,20 +733,20 @@ function aksrt_captcha_error(string $code, string $message, array $data = []): \
*
* @return array|\WP_Error
*/
function aksrt_captcha_remote_json(string $provider, $response) {
function jio_captcha_remote_json(string $provider, $response) {
if (is_wp_error($response)) {
aksrt_captcha_log($provider, $response->get_error_message());
return aksrt_captcha_error('aksrt_captcha_transport', __('人机验证服务暂不可用,请稍后重试', 'aksrt'));
jio_captcha_log($provider, $response->get_error_message());
return jio_captcha_error('jio_captcha_transport', __('人机验证服务暂不可用,请稍后重试', 'jio'));
}
$status = (int) wp_remote_retrieve_response_code($response);
if ($status < 200 || $status >= 300) {
aksrt_captcha_log($provider, 'HTTP ' . $status . ': ' . substr((string) wp_remote_retrieve_body($response), 0, 500));
return aksrt_captcha_error('aksrt_captcha_http', __('人机验证服务暂不可用,请稍后重试', 'aksrt'), ['status' => $status]);
jio_captcha_log($provider, 'HTTP ' . $status . ': ' . substr((string) wp_remote_retrieve_body($response), 0, 500));
return jio_captcha_error('jio_captcha_http', __('人机验证服务暂不可用,请稍后重试', 'jio'), ['status' => $status]);
}
$body = json_decode(wp_remote_retrieve_body($response), true);
if (!is_array($body)) {
aksrt_captcha_log($provider, 'unparsable response');
return aksrt_captcha_error('aksrt_captcha_response', __('人机验证服务暂不可用,请稍后重试', 'aksrt'));
jio_captcha_log($provider, 'unparsable response');
return jio_captcha_error('jio_captcha_response', __('人机验证服务暂不可用,请稍后重试', 'jio'));
}
return $body;
}
@@ -756,26 +756,26 @@ function aksrt_captcha_remote_json(string $provider, $response) {
*
* @return true|\WP_Error
*/
function aksrt_verify_captcha_provider(string $provider, array $pcfg, array $post_data, string $client_ip, string $scene = '', string $action = 'aksrt-verify') {
if (!in_array($provider, aksrt_captcha_providers(), true)) {
return aksrt_captcha_error('aksrt_captcha_provider', __('未知的人机验证服务商', 'aksrt'));
function jio_verify_captcha_provider(string $provider, array $pcfg, array $post_data, string $client_ip, string $scene = '', string $action = 'jio-verify') {
if (!in_array($provider, jio_captcha_providers(), true)) {
return jio_captcha_error('jio_captcha_provider', __('未知的人机验证服务商', 'jio'));
}
if (!aksrt_captcha_provider_is_configured($provider, $pcfg)) {
return aksrt_captcha_error('aksrt_captcha_config', __('验证码配置不完整', 'aksrt'));
if (!jio_captcha_provider_is_configured($provider, $pcfg)) {
return jio_captcha_error('jio_captcha_config', __('验证码配置不完整', 'jio'));
}
switch ($provider) {
case 'tencent':
return aksrt_verify_tencent($pcfg, $post_data, $client_ip);
return jio_verify_tencent($pcfg, $post_data, $client_ip);
case 'cloudflare':
return aksrt_verify_cloudflare($pcfg, $post_data, $client_ip, $scene, $action);
return jio_verify_cloudflare($pcfg, $post_data, $client_ip, $scene, $action);
case 'geetest':
return aksrt_verify_geetest($pcfg, $post_data);
return jio_verify_geetest($pcfg, $post_data);
case 'aliyun':
return aksrt_verify_aliyun($pcfg, $post_data);
return jio_verify_aliyun($pcfg, $post_data);
}
return aksrt_captcha_error('aksrt_captcha_provider', __('未知的人机验证服务商', 'aksrt'));
return jio_captcha_error('jio_captcha_provider', __('未知的人机验证服务商', 'jio'));
}
/**
@@ -783,20 +783,20 @@ function aksrt_verify_captcha_provider(string $provider, array $pcfg, array $pos
*
* @return true|\WP_Error
*/
function aksrt_verify_tencent(array $pcfg, array $post_data, string $client_ip) {
function jio_verify_tencent(array $pcfg, array $post_data, string $client_ip) {
$ticket = (string) ($post_data['tencent_ticket'] ?? '');
$randstr = (string) ($post_data['tencent_randstr'] ?? '');
if ($ticket === '' || $randstr === '') {
return aksrt_captcha_error('aksrt_captcha_missing', __('缺少验证参数', 'aksrt'));
return jio_captcha_error('jio_captcha_missing', __('缺少验证参数', 'jio'));
}
if (str_starts_with($ticket, 'trerror_')) {
return aksrt_captcha_error('aksrt_captcha_disaster_ticket', __('验证码 SDK 异常,请刷新页面重试(容灾票据)', 'aksrt'));
return jio_captcha_error('jio_captcha_disaster_ticket', __('验证码 SDK 异常,请刷新页面重试(容灾票据)', 'jio'));
}
$secret_id = (string) ($pcfg['secret_id'] ?? '');
$secret_key = (string) ($pcfg['secret_key'] ?? '');
if ($secret_id === '' || $secret_key === '') {
return aksrt_captcha_error('aksrt_captcha_config', __('验证码配置不完整:缺少云 API 密钥 (SecretId/SecretKey)', 'aksrt'));
return jio_captcha_error('jio_captcha_config', __('验证码配置不完整:缺少云 API 密钥 (SecretId/SecretKey)', 'jio'));
}
$timestamp = time();
@@ -810,21 +810,21 @@ function aksrt_verify_tencent(array $pcfg, array $post_data, string $client_ip)
'UserIp' => $client_ip,
]);
$headers = aksrt_tencent_tc3_sign($secret_id, $secret_key, 'captcha', $timestamp, $date, 'DescribeCaptchaResult', '2019-07-22', $payload);
$headers = jio_tencent_tc3_sign($secret_id, $secret_key, 'captcha', $timestamp, $date, 'DescribeCaptchaResult', '2019-07-22', $payload);
$resp = wp_remote_post('https://captcha.tencentcloudapi.com/', [
'timeout' => 5,
'headers' => $headers,
'body' => $payload,
]);
$body = aksrt_captcha_remote_json('tencent', $resp);
$body = jio_captcha_remote_json('tencent', $resp);
if (is_wp_error($body)) {
return $body;
}
if (isset($body['Response']['Error'])) {
$err = $body['Response']['Error'];
aksrt_captcha_log('tencent', ($err['Code'] ?? 'unknown') . ': ' . ($err['Message'] ?? ''));
return aksrt_captcha_error('aksrt_captcha_provider_error', __('人机验证服务暂不可用,请稍后重试', 'aksrt'));
jio_captcha_log('tencent', ($err['Code'] ?? 'unknown') . ': ' . ($err['Message'] ?? ''));
return jio_captcha_error('jio_captcha_provider_error', __('人机验证服务暂不可用,请稍后重试', 'jio'));
}
$resp_data = $body['Response'] ?? [];
@@ -844,8 +844,8 @@ function aksrt_verify_tencent(array $pcfg, array $post_data, string $client_ip)
100 => '参数校验失败(AppId/SecretKey/Ticket 不匹配)',
];
$msg = (string) ($resp_data['CaptchaMsg'] ?? ($messages[$captcha_code] ?? '未知错误'));
aksrt_captcha_log('tencent', $msg . " (CaptchaCode: {$captcha_code})");
return aksrt_captcha_error('aksrt_captcha_rejected', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('tencent', $msg . " (CaptchaCode: {$captcha_code})");
return jio_captcha_error('jio_captcha_rejected', __('人机验证未通过,请重试', 'jio'));
}
/**
@@ -853,10 +853,10 @@ function aksrt_verify_tencent(array $pcfg, array $post_data, string $client_ip)
*
* @return true|\WP_Error
*/
function aksrt_verify_cloudflare(array $pcfg, array $post_data, string $client_ip, string $scene = '', string $action = 'aksrt-verify') {
function jio_verify_cloudflare(array $pcfg, array $post_data, string $client_ip, string $scene = '', string $action = 'jio-verify') {
$token = (string) ($post_data['cf_turnstile_response'] ?? '');
if ($token === '' || strlen($token) < 10) {
return aksrt_captcha_error('aksrt_captcha_missing', __('缺少验证参数', 'aksrt'));
return jio_captcha_error('jio_captcha_missing', __('缺少验证参数', 'jio'));
}
$resp = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
@@ -867,29 +867,29 @@ function aksrt_verify_cloudflare(array $pcfg, array $post_data, string $client_i
'remoteip' => $client_ip,
],
]);
$body = aksrt_captcha_remote_json('cloudflare', $resp);
$body = jio_captcha_remote_json('cloudflare', $resp);
if (is_wp_error($body)) {
return $body;
}
if (empty($body['success'])) {
aksrt_captcha_log('cloudflare', 'siteverify failed: ' . implode(', ', (array) ($body['error-codes'] ?? [])));
return aksrt_captcha_error('aksrt_captcha_rejected', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('cloudflare', 'siteverify failed: ' . implode(', ', (array) ($body['error-codes'] ?? [])));
return jio_captcha_error('jio_captcha_rejected', __('人机验证未通过,请重试', 'jio'));
}
if (!array_key_exists('action', $body) || (string) $body['action'] !== $action) {
aksrt_captcha_log('cloudflare', 'action mismatch: ' . (string) ($body['action'] ?? '<missing>') . ' != ' . $action);
return aksrt_captcha_error('aksrt_captcha_action', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('cloudflare', 'action mismatch: ' . (string) ($body['action'] ?? '<missing>') . ' != ' . $action);
return jio_captcha_error('jio_captcha_action', __('人机验证未通过,请重试', 'jio'));
}
if (!array_key_exists('cdata', $body) || (string) $body['cdata'] !== $scene) {
aksrt_captcha_log('cloudflare', 'cdata mismatch: ' . (string) ($body['cdata'] ?? '<missing>') . ' != ' . $scene);
return aksrt_captcha_error('aksrt_captcha_cdata', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('cloudflare', 'cdata mismatch: ' . (string) ($body['cdata'] ?? '<missing>') . ' != ' . $scene);
return jio_captcha_error('jio_captcha_cdata', __('人机验证未通过,请重试', 'jio'));
}
$expected_host = strtolower((string) wp_parse_url(home_url('/'), PHP_URL_HOST));
$response_host = strtolower(trim((string) ($body['hostname'] ?? '')));
if ($expected_host === '' || $response_host === '' || !hash_equals($expected_host, $response_host)) {
aksrt_captcha_log('cloudflare', 'hostname mismatch: ' . ($response_host ?: '<missing>') . ' != ' . ($expected_host ?: '<missing>'));
return aksrt_captcha_error('aksrt_captcha_hostname', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('cloudflare', 'hostname mismatch: ' . ($response_host ?: '<missing>') . ' != ' . ($expected_host ?: '<missing>'));
return jio_captcha_error('jio_captcha_hostname', __('人机验证未通过,请重试', 'jio'));
}
return true;
@@ -900,13 +900,13 @@ function aksrt_verify_cloudflare(array $pcfg, array $post_data, string $client_i
*
* @return true|\WP_Error
*/
function aksrt_verify_geetest(array $pcfg, array $post_data) {
function jio_verify_geetest(array $pcfg, array $post_data) {
$lot_number = (string) ($post_data['geetest_lot_number'] ?? '');
$captcha_output = (string) ($post_data['geetest_captcha_output'] ?? '');
$pass_token = (string) ($post_data['geetest_pass_token'] ?? '');
$gen_time = (string) ($post_data['geetest_gen_time'] ?? '');
if ($lot_number === '' || $captcha_output === '' || $pass_token === '') {
return aksrt_captcha_error('aksrt_captcha_missing', __('缺少验证参数', 'aksrt'));
return jio_captcha_error('jio_captcha_missing', __('缺少验证参数', 'jio'));
}
$captcha_key = (string) ($pcfg['captcha_key'] ?? '');
@@ -924,15 +924,15 @@ function aksrt_verify_geetest(array $pcfg, array $post_data) {
],
]);
$body = aksrt_captcha_remote_json('geetest', $resp);
$body = jio_captcha_remote_json('geetest', $resp);
if (is_wp_error($body)) {
return $body;
}
if (($body['result'] ?? '') === 'success') {
return true;
}
aksrt_captcha_log('geetest', 'validate failed: ' . (string) ($body['reason'] ?? ($body['msg'] ?? 'unknown')));
return aksrt_captcha_error('aksrt_captcha_rejected', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('geetest', 'validate failed: ' . (string) ($body['reason'] ?? ($body['msg'] ?? 'unknown')));
return jio_captcha_error('jio_captcha_rejected', __('人机验证未通过,请重试', 'jio'));
}
/**
@@ -940,10 +940,10 @@ function aksrt_verify_geetest(array $pcfg, array $post_data) {
*
* @return true|\WP_Error
*/
function aksrt_verify_aliyun(array $pcfg, array $post_data) {
function jio_verify_aliyun(array $pcfg, array $post_data) {
$captcha_verify_param = (string) ($post_data['aliyun_captcha_verify_param'] ?? '');
if ($captcha_verify_param === '') {
return aksrt_captcha_error('aksrt_captcha_missing', __('缺少验证参数 (captchaVerifyParam)', 'aksrt'));
return jio_captcha_error('jio_captcha_missing', __('缺少验证参数 (captchaVerifyParam)', 'jio'));
}
$region = (string) ($pcfg['region'] ?? 'cn');
@@ -965,14 +965,14 @@ function aksrt_verify_aliyun(array $pcfg, array $post_data) {
if (!empty($pcfg['scene_id'])) {
$params['SceneId'] = (string) $pcfg['scene_id'];
}
$params['Signature'] = aksrt_aliyun_afs_sign($params, (string) ($pcfg['access_key_secret'] ?? ''));
$params['Signature'] = jio_aliyun_afs_sign($params, (string) ($pcfg['access_key_secret'] ?? ''));
$resp = wp_remote_post('https://' . $endpoint . '/', [
'timeout' => 5,
'body' => $params,
]);
$body = aksrt_captcha_remote_json('aliyun', $resp);
$body = jio_captcha_remote_json('aliyun', $resp);
if (is_wp_error($body)) {
return $body;
}
@@ -1001,12 +1001,12 @@ function aksrt_verify_aliyun(array $pcfg, array $post_data) {
];
$verify_code = (string) ($body['Result']['VerifyCode'] ?? '');
$detail = $code_messages[$verify_code] ?? '未知错误 (' . ($verify_code ?: 'N/A') . ')';
aksrt_captcha_log('aliyun', 'verify rejected: ' . $detail);
return aksrt_captcha_error('aksrt_captcha_rejected', __('人机验证未通过,请重试', 'aksrt'));
jio_captcha_log('aliyun', 'verify rejected: ' . $detail);
return jio_captcha_error('jio_captcha_rejected', __('人机验证未通过,请重试', 'jio'));
}
aksrt_captcha_log('aliyun', 'api failed: ' . (string) ($body['Message'] ?? 'unknown'));
return aksrt_captcha_error('aksrt_captcha_provider_error', __('人机验证服务暂不可用,请稍后重试', 'aksrt'));
jio_captcha_log('aliyun', 'api failed: ' . (string) ($body['Message'] ?? 'unknown'));
return jio_captcha_error('jio_captcha_provider_error', __('人机验证服务暂不可用,请稍后重试', 'jio'));
}
// ============================================================
@@ -1018,22 +1018,22 @@ function aksrt_verify_aliyun(array $pcfg, array $post_data) {
*
* 挂载点自带 JSON 配置,由 captcha-front.js(public bundle)扫描激活。
*/
function aksrt_render_captcha($scene = 'comment') {
function jio_render_captcha($scene = 'comment') {
$scene = sanitize_key((string) $scene);
if (!aksrt_is_captcha_enabled_for($scene)) {
if (!jio_is_captcha_enabled_for($scene)) {
return;
}
$cfg = aksrt_get_captcha_config();
$cfg = jio_get_captcha_config();
$provider = $cfg['active_provider'];
$pcfg = $cfg[$provider] ?? [];
if (!aksrt_captcha_provider_is_configured($provider, $pcfg)) {
if (!jio_captcha_provider_is_configured($provider, $pcfg)) {
if (current_user_can('manage_options')) {
echo '<div class="aksrt-captcha-misconfig" style="font-size:12px;color:#d03050;margin:8px 0;">';
echo '<div class="jio-captcha-misconfig" style="font-size:12px;color:#d03050;margin:8px 0;">';
echo esc_html(sprintf(
/* translators: %s: captcha provider key */
__('人机验证服务商「%s」已启用但凭据未配齐,当前场景将拒绝提交。请到「功能&权限 → 人机验证」补全配置。', 'aksrt'),
__('人机验证服务商「%s」已启用但凭据未配齐,当前场景将拒绝提交。请到「功能&权限 → 人机验证」补全配置。', 'jio'),
$provider
));
echo '</div>';
@@ -1041,7 +1041,7 @@ function aksrt_render_captcha($scene = 'comment') {
return;
}
$uid = 'aksrt-captcha-' . $scene . '-' . wp_unique_id();
$uid = 'jio-captcha-' . $scene . '-' . wp_unique_id();
$vid = 'captcha_verified_' . $scene . '_' . wp_unique_id();
$js_config = [
@@ -1049,8 +1049,8 @@ function aksrt_render_captcha($scene = 'comment') {
'scene' => $scene,
'uid' => $uid,
'vid' => $vid,
'challenge_url' => rest_url('aksrt/v1/captcha/challenge'),
'exchange_url' => rest_url('aksrt/v1/captcha/exchange'),
'challenge_url' => rest_url('jio/v1/captcha/challenge'),
'exchange_url' => rest_url('jio/v1/captcha/exchange'),
'tc' => ['app_id' => (string) ($pcfg['app_id'] ?? '')],
'cf' => [
'site_key' => (string) ($pcfg['site_key'] ?? ''),
@@ -1068,11 +1068,11 @@ function aksrt_render_captcha($scene = 'comment') {
],
];
?>
<div class="aksrt-captcha-wrap" data-provider="<?php echo esc_attr($provider); ?>" data-scene="<?php echo esc_attr($scene); ?>" data-aksrt-captcha-config="<?php echo esc_attr(wp_json_encode($js_config, JSON_UNESCAPED_UNICODE)); ?>">
<div id="<?php echo esc_attr($uid); ?>" class="aksrt-captcha-box" style="display:none"></div>
<div class="jio-captcha-wrap" data-provider="<?php echo esc_attr($provider); ?>" data-scene="<?php echo esc_attr($scene); ?>" data-jio-captcha-config="<?php echo esc_attr(wp_json_encode($js_config, JSON_UNESCAPED_UNICODE)); ?>">
<div id="<?php echo esc_attr($uid); ?>" class="jio-captcha-box" style="display:none"></div>
<input type="hidden" name="captcha_verified" id="<?php echo esc_attr($vid); ?>" value="0">
<input type="hidden" name="aksrt_captcha_challenge" value="">
<input type="hidden" name="aksrt_captcha_proof" value="">
<input type="hidden" name="jio_captcha_challenge" value="">
<input type="hidden" name="jio_captcha_proof" value="">
</div>
<?php
}
+2 -2
View File
@@ -1,8 +1,8 @@
<?php
/**
* Creator revenue class lives at AKSRT\Payment\CreatorRevenue (Composer).
* Creator revenue class lives at Jio\Payment\CreatorRevenue (Composer).
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
+72 -72
View File
@@ -2,35 +2,35 @@
/**
* Message center query and server-side fragment renderers.
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
/** @return array<string,string> */
function aksrt_message_center_views(): array {
function jio_message_center_views(): array {
return [
'unread' => __('未读消息', 'aksrt'),
'posts' => __('文章评论', 'aksrt'),
'like' => __('点赞喜欢', 'aksrt'),
'system' => __('系统通知', 'aksrt'),
'unread' => __('未读消息', 'jio'),
'posts' => __('文章评论', 'jio'),
'like' => __('点赞喜欢', 'jio'),
'system' => __('系统通知', 'jio'),
];
}
function aksrt_normalize_message_view(string $view): string {
function jio_normalize_message_view(string $view): string {
$view = sanitize_key($view);
return array_key_exists($view, aksrt_message_center_views()) ? $view : 'unread';
return array_key_exists($view, jio_message_center_views()) ? $view : 'unread';
}
function aksrt_get_message_center_paginate_type(): string {
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::notification_settings()
function jio_get_message_center_paginate_type(): string {
$settings = class_exists('\Jio\Settings\Settings')
? \Jio\Settings\Settings::notification_settings()
: [];
$type = sanitize_key((string) ($settings['paginate_type'] ?? 'ajax_lists'));
return in_array($type, ['ajax_lists', 'default'], true) ? $type : 'ajax_lists';
}
function aksrt_message_category_for_type(string $type): string {
function jio_message_category_for_type(string $type): string {
$type = sanitize_key($type);
if (str_starts_with($type, 'asset_')) {
return '';
@@ -54,14 +54,14 @@ function aksrt_message_category_for_type(string $type): string {
}
/** @return array<int,array<string,mixed>> */
function aksrt_get_message_center_items(int $user_id, string $view): array {
$view = aksrt_normalize_message_view($view);
$items = function_exists('aksrt_get_user_all_notifications')
? aksrt_get_user_all_notifications($user_id)
function jio_get_message_center_items(int $user_id, string $view): array {
$view = jio_normalize_message_view($view);
$items = function_exists('jio_get_user_all_notifications')
? jio_get_user_all_notifications($user_id)
: [];
return array_values(array_filter($items, static function (array $item) use ($view): bool {
$category = aksrt_message_category_for_type((string) ($item['type'] ?? 'notice'));
$category = jio_message_category_for_type((string) ($item['type'] ?? 'notice'));
if ($category === '') {
return false;
}
@@ -73,14 +73,14 @@ function aksrt_get_message_center_items(int $user_id, string $view): array {
}
/** @return array{unread:int,posts:int,like:int,system:int} */
function aksrt_get_message_center_counts(int $user_id): array {
function jio_get_message_center_counts(int $user_id): array {
$counts = ['unread' => 0, 'posts' => 0, 'like' => 0, 'system' => 0];
$items = function_exists('aksrt_get_user_all_notifications')
? aksrt_get_user_all_notifications($user_id)
$items = function_exists('jio_get_user_all_notifications')
? jio_get_user_all_notifications($user_id)
: [];
foreach ($items as $item) {
$category = aksrt_message_category_for_type((string) ($item['type'] ?? 'notice'));
$category = jio_message_category_for_type((string) ($item['type'] ?? 'notice'));
if ($category === '' || !empty($item['read'])) {
continue;
}
@@ -91,19 +91,19 @@ function aksrt_get_message_center_counts(int $user_id): array {
}
/** @return array<string,mixed>|null */
function aksrt_get_message_center_item(int $user_id, int $notification_id): ?array {
function jio_get_message_center_item(int $user_id, int $notification_id): ?array {
if ($user_id <= 0 || $notification_id <= 0) {
return null;
}
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
if ($table === '') return null;
$row = $wpdb->get_row($wpdb->prepare(
"SELECT id, type, title, description, target_url, is_read, created_at, read_at FROM {$table} WHERE id = %d AND user_id = %d",
$notification_id,
$user_id
), ARRAY_A);
if (!is_array($row) || aksrt_message_category_for_type((string) ($row['type'] ?? 'notice')) === '') return null;
if (!is_array($row) || jio_message_category_for_type((string) ($row['type'] ?? 'notice')) === '') return null;
return [
'id' => (string) $row['id'],
'type' => (string) $row['type'],
@@ -116,7 +116,7 @@ function aksrt_get_message_center_item(int $user_id, int $notification_id): ?arr
];
}
function aksrt_message_icon_class(string $type): string {
function jio_message_icon_class(string $type): string {
$icons = [
'comment_reply' => 'fa fas fa-comment-dots',
'comment_approved' => 'fa fas fa-check-circle',
@@ -143,21 +143,21 @@ function aksrt_message_icon_class(string $type): string {
return $icons[$type] ?? 'fa fas fa-bell';
}
function aksrt_message_time(array $item): string {
function jio_message_time(array $item): string {
if (!empty($item['stateful'])) {
return __('状态提醒', 'aksrt');
return __('状态提醒', 'jio');
}
$created_at = (string) ($item['created_at'] ?? '');
return $created_at !== '' ? get_date_from_gmt($created_at, 'Y-m-d H:i') : '';
}
function aksrt_render_message_center_nav(string $view, array $counts): void {
$view = aksrt_normalize_message_view($view);
function jio_render_message_center_nav(string $view, array $counts): void {
$view = jio_normalize_message_view($view);
?>
<ul class="messages-nav__list">
<?php foreach (aksrt_message_center_views() as $key => $label) : ?>
<?php foreach (jio_message_center_views() as $key => $label) : ?>
<li>
<a href="<?php echo esc_url(aksrt_get_messages_page_url($key)); ?>"
<a href="<?php echo esc_url(jio_get_messages_page_url($key)); ?>"
class="messages-nav__item<?php echo $view === $key ? ' is-active' : ''; ?>"
data-message-view="<?php echo esc_attr($key); ?>"
<?php echo $view === $key ? 'aria-current="page"' : ''; ?>>
@@ -168,13 +168,13 @@ function aksrt_render_message_center_nav(string $view, array $counts): void {
<?php endforeach; ?>
</ul>
<div class="messages-nav__actions">
<button type="button" class="messages-nav__action-btn js-msg-mark-all-read"><?php esc_html_e('全部已读', 'aksrt'); ?></button>
<button type="button" class="messages-nav__action-btn js-msg-clear-read"><?php esc_html_e('清除已读', 'aksrt'); ?></button>
<button type="button" class="messages-nav__action-btn js-msg-mark-all-read"><?php esc_html_e('全部已读', 'jio'); ?></button>
<button type="button" class="messages-nav__action-btn js-msg-clear-read"><?php esc_html_e('清除已读', 'jio'); ?></button>
</div>
<?php
}
function aksrt_render_message_item(array $item, string $view): void {
function jio_render_message_item(array $item, string $view): void {
$type = (string) ($item['type'] ?? 'notice');
$id = (string) ($item['id'] ?? '');
$title = (string) ($item['title'] ?? '');
@@ -184,60 +184,60 @@ function aksrt_render_message_item(array $item, string $view): void {
$is_stateful = !empty($item['stateful']);
?>
<article class="message-item<?php echo $is_read ? '' : ' is-unread'; ?>" data-notification-id="<?php echo esc_attr($id); ?>">
<span class="message-item__icon"><i class="<?php echo esc_attr(aksrt_message_icon_class($type)); ?>" aria-hidden="true"></i></span>
<span class="message-item__icon"><i class="<?php echo esc_attr(jio_message_icon_class($type)); ?>" aria-hidden="true"></i></span>
<div class="message-item__body">
<?php if (!$is_stateful) : ?>
<button type="button" class="message-item__title js-msg-detail" data-id="<?php echo esc_attr($id); ?>" data-view="<?php echo esc_attr($view); ?>">
<?php echo esc_html($title); ?>
<?php if (!$is_read) : ?><span class="message-item__new-badge"><?php esc_html_e('新', 'aksrt'); ?></span><?php endif; ?>
<?php if (!$is_read) : ?><span class="message-item__new-badge"><?php esc_html_e('新', 'jio'); ?></span><?php endif; ?>
</button>
<?php else : ?>
<div class="message-item__title"><?php echo esc_html($title); ?></div>
<?php endif; ?>
<?php if ($description !== '') : ?><div class="message-item__desc"><?php echo esc_html($description); ?></div><?php endif; ?>
<div class="message-item__time"><?php echo esc_html(aksrt_message_time($item)); ?></div>
<div class="message-item__time"><?php echo esc_html(jio_message_time($item)); ?></div>
</div>
<div class="message-item__actions">
<?php if ($is_stateful && $target_url !== '') : ?><a href="<?php echo esc_url($target_url); ?>" class="message-item__action-btn"><?php esc_html_e('立即处理', 'aksrt'); ?></a><?php endif; ?>
<?php if (!$is_stateful) : ?><button type="button" class="message-item__action-btn js-msg-detail" data-id="<?php echo esc_attr($id); ?>" data-view="<?php echo esc_attr($view); ?>"><?php esc_html_e('详情', 'aksrt'); ?></button><?php endif; ?>
<?php if (!$is_stateful && !$is_read) : ?><button type="button" class="message-item__action-btn js-msg-mark-read" data-id="<?php echo esc_attr($id); ?>"><?php esc_html_e('已读', 'aksrt'); ?></button><?php endif; ?>
<?php if (!$is_stateful) : ?><button type="button" class="message-item__action-btn message-item__action-btn--danger js-msg-delete" data-id="<?php echo esc_attr($id); ?>"><?php esc_html_e('删除', 'aksrt'); ?></button><?php endif; ?>
<?php if ($is_stateful && $target_url !== '') : ?><a href="<?php echo esc_url($target_url); ?>" class="message-item__action-btn"><?php esc_html_e('立即处理', 'jio'); ?></a><?php endif; ?>
<?php if (!$is_stateful) : ?><button type="button" class="message-item__action-btn js-msg-detail" data-id="<?php echo esc_attr($id); ?>" data-view="<?php echo esc_attr($view); ?>"><?php esc_html_e('详情', 'jio'); ?></button><?php endif; ?>
<?php if (!$is_stateful && !$is_read) : ?><button type="button" class="message-item__action-btn js-msg-mark-read" data-id="<?php echo esc_attr($id); ?>"><?php esc_html_e('已读', 'jio'); ?></button><?php endif; ?>
<?php if (!$is_stateful) : ?><button type="button" class="message-item__action-btn message-item__action-btn--danger js-msg-delete" data-id="<?php echo esc_attr($id); ?>"><?php esc_html_e('删除', 'jio'); ?></button><?php endif; ?>
</div>
</article>
<?php
}
function aksrt_render_message_center_list(int $user_id, string $view, int $page = 1): void {
$items = aksrt_get_message_center_items($user_id, $view);
function jio_render_message_center_list(int $user_id, string $view, int $page = 1): void {
$items = jio_get_message_center_items($user_id, $view);
$per_page = 20;
$total_pages = max(1, (int) ceil(count($items) / $per_page));
$page = max(1, min($total_pages, $page));
$paginate_type = aksrt_get_message_center_paginate_type();
$paginate_type = jio_get_message_center_paginate_type();
$items = $paginate_type === 'ajax_lists'
? array_slice($items, 0, $page * $per_page)
: array_slice($items, ($page - 1) * $per_page, $per_page);
if (!$items) {
?>
<div class="messages-empty"><span class="messages-empty__icon"><i class="fa fas fa-bell-slash"></i></span><p class="messages-empty__text"><?php esc_html_e('暂无消息', 'aksrt'); ?></p></div>
<div class="messages-empty"><span class="messages-empty__icon"><i class="fa fas fa-bell-slash"></i></span><p class="messages-empty__text"><?php esc_html_e('暂无消息', 'jio'); ?></p></div>
<?php
return;
}
?>
<div class="messages-list">
<?php foreach ($items as $item) { aksrt_render_message_item($item, $view); } ?>
<?php foreach ($items as $item) { jio_render_message_item($item, $view); } ?>
<?php
if (function_exists('aksrt_get_message_placeholder')) {
echo aksrt_get_message_placeholder(4); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 固定骨架结构。
if (function_exists('jio_get_message_placeholder')) {
echo jio_get_message_placeholder(4); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 固定骨架结构。
}
?>
</div>
<?php if ($total_pages > 1) : ?>
<?php if ($paginate_type === 'ajax_lists' && $page < $total_pages) : ?>
<nav class="messages-pagination messages-pagination--load-more" aria-label="<?php esc_attr_e('消息分页', 'aksrt'); ?>">
<nav class="messages-pagination messages-pagination--load-more" aria-label="<?php esc_attr_e('消息分页', 'jio'); ?>">
<button type="button" class="messages-pagination__more" data-message-next-page="<?php echo esc_attr((string) ($page + 1)); ?>">
<span><?php esc_html_e('加载更多消息', 'aksrt'); ?></span>
<small><?php echo esc_html(sprintf(__('%1$d / %2$d 页', 'aksrt'), $page, $total_pages)); ?></small>
<span><?php esc_html_e('加载更多消息', 'jio'); ?></span>
<small><?php echo esc_html(sprintf(__('%1$d / %2$d 页', 'jio'), $page, $total_pages)); ?></small>
</button>
</nav>
<?php elseif ($paginate_type === 'default') : ?>
@@ -254,69 +254,69 @@ function aksrt_render_message_center_list(int $user_id, string $view, int $page
sort($numbers);
$previous_number = 0;
?>
<nav class="messages-pagination messages-pagination--numbers" aria-label="<?php esc_attr_e('消息分页', 'aksrt'); ?>">
<button type="button" class="messages-pagination__button messages-pagination__button--edge" data-message-page="<?php echo esc_attr((string) max(1, $page - 1)); ?>" aria-label="<?php esc_attr_e('上一页', 'aksrt'); ?>" <?php disabled($page, 1); ?>><i class="fa fas fa-angle-left" aria-hidden="true"></i></button>
<nav class="messages-pagination messages-pagination--numbers" aria-label="<?php esc_attr_e('消息分页', 'jio'); ?>">
<button type="button" class="messages-pagination__button messages-pagination__button--edge" data-message-page="<?php echo esc_attr((string) max(1, $page - 1)); ?>" aria-label="<?php esc_attr_e('上一页', 'jio'); ?>" <?php disabled($page, 1); ?>><i class="fa fas fa-angle-left" aria-hidden="true"></i></button>
<?php foreach ($numbers as $number) : ?>
<?php if ($previous_number > 0 && $number - $previous_number > 1) : ?><span class="messages-pagination__ellipsis" aria-hidden="true">…</span><?php endif; ?>
<button type="button" class="messages-pagination__button<?php echo $number === $page ? ' is-current' : ''; ?>" data-message-page="<?php echo esc_attr((string) $number); ?>" <?php echo $number === $page ? 'aria-current="page"' : ''; ?> <?php disabled($number, $page); ?>><?php echo esc_html((string) $number); ?></button>
<?php $previous_number = $number; ?>
<?php endforeach; ?>
<button type="button" class="messages-pagination__button messages-pagination__button--edge" data-message-page="<?php echo esc_attr((string) min($total_pages, $page + 1)); ?>" aria-label="<?php esc_attr_e('下一页', 'aksrt'); ?>" <?php disabled($page, $total_pages); ?>><i class="fa fas fa-angle-right" aria-hidden="true"></i></button>
<button type="button" class="messages-pagination__button messages-pagination__button--edge" data-message-page="<?php echo esc_attr((string) min($total_pages, $page + 1)); ?>" aria-label="<?php esc_attr_e('下一页', 'jio'); ?>" <?php disabled($page, $total_pages); ?>><i class="fa fas fa-angle-right" aria-hidden="true"></i></button>
</nav>
<?php endif; ?>
<?php endif;
}
function aksrt_render_message_center_detail(array $item, string $view): void {
function jio_render_message_center_detail(array $item, string $view): void {
$type = (string) ($item['type'] ?? 'notice');
?>
<article class="message-detail" data-notification-id="<?php echo esc_attr((string) ($item['id'] ?? '')); ?>">
<header class="message-detail__header">
<button type="button" class="message-detail__back" data-message-back data-view="<?php echo esc_attr($view); ?>"><i class="fa fas fa-arrow-left" aria-hidden="true"></i> <?php esc_html_e('返回消息列表', 'aksrt'); ?></button>
<span class="message-detail__icon"><i class="<?php echo esc_attr(aksrt_message_icon_class($type)); ?>" aria-hidden="true"></i></span>
<button type="button" class="message-detail__back" data-message-back data-view="<?php echo esc_attr($view); ?>"><i class="fa fas fa-arrow-left" aria-hidden="true"></i> <?php esc_html_e('返回消息列表', 'jio'); ?></button>
<span class="message-detail__icon"><i class="<?php echo esc_attr(jio_message_icon_class($type)); ?>" aria-hidden="true"></i></span>
<h2 class="message-detail__title"><?php echo esc_html((string) ($item['title'] ?? '')); ?></h2>
<p class="message-detail__meta"><?php echo esc_html(aksrt_message_time($item)); ?></p>
<p class="message-detail__meta"><?php echo esc_html(jio_message_time($item)); ?></p>
</header>
<div class="message-detail__content"><?php echo wp_kses_post(wpautop(esc_html((string) ($item['desc'] ?? '')))); ?></div>
<footer class="message-detail__actions">
<button type="button" class="message-item__action-btn message-item__action-btn--danger js-msg-delete" data-id="<?php echo esc_attr((string) ($item['id'] ?? '')); ?>" data-detail="1"><?php esc_html_e('删除消息', 'aksrt'); ?></button>
<button type="button" class="message-item__action-btn message-item__action-btn--danger js-msg-delete" data-id="<?php echo esc_attr((string) ($item['id'] ?? '')); ?>" data-detail="1"><?php esc_html_e('删除消息', 'jio'); ?></button>
</footer>
</article>
<?php
}
add_action('wp_ajax_aksrt_load_message_center', function (): void {
add_action('wp_ajax_jio_load_message_center', function (): void {
if (!is_user_logged_in()) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')], 401);
wp_send_json_error(['message' => __('请先登录', 'jio')], 401);
}
$nonce = isset($_POST['nonce']) ? (string) wp_unslash($_POST['nonce']) : '';
if (!wp_verify_nonce($nonce, 'aksrt_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'aksrt')], 403);
if (!wp_verify_nonce($nonce, 'jio_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'jio')], 403);
}
$user_id = get_current_user_id();
$view = aksrt_normalize_message_view((string) ($_POST['view'] ?? 'unread'));
$view = jio_normalize_message_view((string) ($_POST['view'] ?? 'unread'));
$page = max(1, absint($_POST['page'] ?? 1));
$notification_id = absint($_POST['notification_id'] ?? 0);
$detail = null;
if ($notification_id > 0) {
$detail = aksrt_get_message_center_item($user_id, $notification_id);
$detail = jio_get_message_center_item($user_id, $notification_id);
if (!$detail) {
wp_send_json_error(['message' => __('消息不存在或已删除', 'aksrt')], 404);
wp_send_json_error(['message' => __('消息不存在或已删除', 'jio')], 404);
}
aksrt_mark_user_notification_read($user_id, (string) $notification_id);
jio_mark_user_notification_read($user_id, (string) $notification_id);
$detail['read'] = 1;
}
$counts = aksrt_get_message_center_counts($user_id);
$counts = jio_get_message_center_counts($user_id);
ob_start();
aksrt_render_message_center_nav($view, $counts);
jio_render_message_center_nav($view, $counts);
$nav_html = (string) ob_get_clean();
ob_start();
if ($detail) {
aksrt_render_message_center_detail($detail, $view);
jio_render_message_center_detail($detail, $view);
} else {
aksrt_render_message_center_list($user_id, $view, $page);
jio_render_message_center_list($user_id, $view, $page);
}
$content_html = (string) ob_get_clean();
@@ -324,7 +324,7 @@ add_action('wp_ajax_aksrt_load_message_center', function (): void {
'view' => $view,
'page' => $page,
'detail' => $notification_id,
'paginate_type' => aksrt_get_message_center_paginate_type(),
'paginate_type' => jio_get_message_center_paginate_type(),
'nav' => $nav_html,
'content' => $content_html,
'unread' => $counts['unread'],
+2 -2
View File
@@ -1,10 +1,10 @@
<?php
/**
* AKSRT User system module hub (procedural).
* Jio User system module hub (procedural).
*
* Loads user-parts/*; keeps historical path for bootstrap.
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
+119 -119
View File
@@ -1,15 +1,15 @@
<?php
/**
* AKSRT User Notifications
* Jio User Notifications
*
* Notification CRUD, AJAX handlers, and event-driven notification creators.
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_user_notifications')) :
if (!function_exists('jio_get_user_notifications')) :
/**
* 获取用户提醒列表(即时提醒,不持久化)
*
@@ -18,7 +18,7 @@ if (!function_exists('aksrt_get_user_notifications')) :
* @param int $user_id 用户 ID,默认当前用户
* @return array<int, array{type:string,title:string,desc:string,url:string,count:int}>
*/
function aksrt_get_user_notifications(int $user_id = 0): array {
function jio_get_user_notifications(int $user_id = 0): array {
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
if ($user_id <= 0) {
return [];
@@ -34,14 +34,14 @@ function aksrt_get_user_notifications(int $user_id = 0): array {
if (
$pending_comments > 0
&& (!class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::notification_enabled('pending_comments'))
&& (!class_exists('\AKSRT\User\NotificationPreferences') || \AKSRT\User\NotificationPreferences::allows($user_id, 'pending_comments'))
&& (!class_exists('\Jio\Settings\Settings') || \Jio\Settings\Settings::notification_enabled('pending_comments'))
&& (!class_exists('\Jio\User\NotificationPreferences') || \Jio\User\NotificationPreferences::allows($user_id, 'pending_comments'))
) {
$items[] = [
'type' => 'pending_comments',
'title' => __('评论待审核', 'aksrt'),
'desc' => sprintf(__('你有 %d 条评论正在等待审核。', 'aksrt'), $pending_comments),
'url' => aksrt_get_user_center_url('comments'),
'title' => __('评论待审核', 'jio'),
'desc' => sprintf(__('你有 %d 条评论正在等待审核。', 'jio'), $pending_comments),
'url' => jio_get_user_center_url('comments'),
'count' => $pending_comments,
];
}
@@ -50,10 +50,10 @@ function aksrt_get_user_notifications(int $user_id = 0): array {
}
endif;
if (!function_exists('aksrt_get_user_notification_count')) :
if (!function_exists('jio_get_user_notification_count')) :
/** 获取用户提醒总数 */
function aksrt_get_user_notification_count(int $user_id = 0): int {
$items = aksrt_get_user_notifications($user_id);
function jio_get_user_notification_count(int $user_id = 0): int {
$items = jio_get_user_notifications($user_id);
$count = 0;
foreach ($items as $item) {
$count += max(0, (int) ($item['count'] ?? 0));
@@ -62,16 +62,16 @@ function aksrt_get_user_notification_count(int $user_id = 0): int {
}
endif;
if (!function_exists('aksrt_get_user_inbox_notifications')) :
if (!function_exists('jio_get_user_inbox_notifications')) :
/** 获取用户通知收件箱 */
function aksrt_get_user_inbox_notifications(int $user_id = 0): array {
function jio_get_user_inbox_notifications(int $user_id = 0): array {
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
if ($user_id <= 0) return [];
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
if ($table === '') return [];
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_notification_settings() : [];
$settings = class_exists('\Jio\Settings\Settings') ? \Jio\Settings\Settings::get_notification_settings() : [];
$limit = max(20, min(5000, (int) ($settings['max_per_user'] ?? 200)));
$rows = $wpdb->get_results($wpdb->prepare(
@@ -101,32 +101,32 @@ function aksrt_get_user_inbox_notifications(int $user_id = 0): array {
}
endif;
if (!function_exists('aksrt_schedule_notification_cleanup')) :
if (!function_exists('jio_schedule_notification_cleanup')) :
/** 注册通知清理定时任务 */
function aksrt_schedule_notification_cleanup(): void {
if (!wp_next_scheduled('aksrt_notification_cleanup')) {
function jio_schedule_notification_cleanup(): void {
if (!wp_next_scheduled('jio_notification_cleanup')) {
$next = (new DateTimeImmutable('tomorrow 04:10', wp_timezone()))->getTimestamp();
wp_schedule_event($next, 'daily', 'aksrt_notification_cleanup');
wp_schedule_event($next, 'daily', 'jio_notification_cleanup');
}
}
endif;
if (!function_exists('aksrt_cleanup_notifications')) :
if (!function_exists('jio_cleanup_notifications')) :
/**
* 清理通知表:
* - 已读通知保留 30 天
* - 未读通知保留 180 天
* - 每个用户最多保留最近 200 条通知
*/
function aksrt_cleanup_notifications(): void {
function jio_cleanup_notifications(): void {
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
if ($table === '') {
return;
}
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_notification_settings() : [
$settings = class_exists('\Jio\Settings\Settings') ? \Jio\Settings\Settings::get_notification_settings() : [
'read_retention_days' => 30,
'unread_retention_days' => 180,
'max_per_user' => 200,
@@ -179,23 +179,23 @@ function aksrt_cleanup_notifications(): void {
}
endif;
add_action('wp', 'aksrt_schedule_notification_cleanup');
add_action('aksrt_notification_cleanup', 'aksrt_cleanup_notifications');
add_action('wp', 'jio_schedule_notification_cleanup');
add_action('jio_notification_cleanup', 'jio_cleanup_notifications');
if (!function_exists('aksrt_add_user_notification')) :
if (!function_exists('jio_add_user_notification')) :
/** 添加一条用户通知 */
function aksrt_add_user_notification(int $user_id, array $payload): void {
function jio_add_user_notification(int $user_id, array $payload): void {
if ($user_id <= 0) return;
$type = sanitize_key((string) ($payload['type'] ?? 'notice'));
if (class_exists('\AKSRT\User\NotificationPreferences') && !\AKSRT\User\NotificationPreferences::allows($user_id, $type)) {
if (class_exists('\Jio\User\NotificationPreferences') && !\Jio\User\NotificationPreferences::allows($user_id, $type)) {
return;
}
if (class_exists('\AKSRT\Settings\Settings') && !\AKSRT\Settings\Settings::notification_enabled($type)) {
if (class_exists('\Jio\Settings\Settings') && !\Jio\Settings\Settings::notification_enabled($type)) {
return;
}
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
$created_at = (string) ($payload['created_at'] ?? current_time('mysql', true));
if ($table === '') return;
@@ -211,7 +211,7 @@ function aksrt_add_user_notification(int $user_id, array $payload): void {
'read_at' => !empty($payload['read']) ? current_time('mysql', true) : null,
], ['%d', '%s', '%s', '%s', '%s', '%d', '%s', '%s']);
if ($inserted !== false) {
do_action('aksrt_notification_sent', $user_id, $type, [
do_action('jio_notification_sent', $user_id, $type, [
'title' => (string) ($payload['title'] ?? ''),
'description' => (string) ($payload['desc'] ?? ''),
'target_url' => (string) ($payload['url'] ?? ''),
@@ -220,12 +220,12 @@ function aksrt_add_user_notification(int $user_id, array $payload): void {
}
endif;
if (!function_exists('aksrt_mark_user_notification_read')) :
if (!function_exists('jio_mark_user_notification_read')) :
/** 标记通知已读 */
function aksrt_mark_user_notification_read(int $user_id, string $notification_id = '', bool $mark_all = false): void {
function jio_mark_user_notification_read(int $user_id, string $notification_id = '', bool $mark_all = false): void {
if ($user_id <= 0) return;
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
if ($table === '') return;
if ($mark_all) {
@@ -249,26 +249,26 @@ function aksrt_mark_user_notification_read(int $user_id, string $notification_id
}
endif;
if (!function_exists('aksrt_delete_user_notification')) :
if (!function_exists('jio_delete_user_notification')) :
/** 删除一条用户通知 */
function aksrt_delete_user_notification(int $user_id, string $notification_id): void {
function jio_delete_user_notification(int $user_id, string $notification_id): void {
if ($user_id <= 0 || $notification_id === '') return;
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
if ($table === '') return;
$wpdb->delete($table, ['id' => absint($notification_id), 'user_id' => $user_id], ['%d', '%d']);
}
endif;
if (!function_exists('aksrt_delete_user_notifications')) :
if (!function_exists('jio_delete_user_notifications')) :
/** 批量删除用户通知 */
function aksrt_delete_user_notifications(int $user_id, array $notification_ids): void {
function jio_delete_user_notifications(int $user_id, array $notification_ids): void {
if ($user_id <= 0 || empty($notification_ids)) return;
$ids = array_values(array_filter(array_map('absint', $notification_ids), static function ($id) { return $id > 0; }));
if (empty($ids)) return;
global $wpdb;
$table = class_exists('\AKSRT\Core\DBMigrator') ? \AKSRT\Core\DBMigrator::table('notification') : '';
$table = class_exists('\Jio\Core\DBMigrator') ? \Jio\Core\DBMigrator::table('notification') : '';
if ($table === '') return;
$wpdb->query(
@@ -277,10 +277,10 @@ function aksrt_delete_user_notifications(int $user_id, array $notification_ids):
}
endif;
if (!function_exists('aksrt_get_user_unread_notification_count')) :
if (!function_exists('jio_get_user_unread_notification_count')) :
/** 获取用户未读通知数 */
function aksrt_get_user_unread_notification_count(int $user_id = 0): int {
$items = aksrt_get_user_inbox_notifications($user_id);
function jio_get_user_unread_notification_count(int $user_id = 0): int {
$items = jio_get_user_inbox_notifications($user_id);
$count = 0;
foreach ($items as $item) {
if (empty($item['read']) && !str_starts_with((string) ($item['type'] ?? ''), 'asset_')) $count++;
@@ -289,33 +289,33 @@ function aksrt_get_user_unread_notification_count(int $user_id = 0): int {
}
endif;
if (!function_exists('aksrt_get_user_tab_badge_count')) :
if (!function_exists('jio_get_user_tab_badge_count')) :
/** user 底部 Tab 徽标计数:未读持久化通知 + 即时状态提醒 */
function aksrt_get_user_tab_badge_count(int $user_id = 0): int {
function jio_get_user_tab_badge_count(int $user_id = 0): int {
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
if ($user_id <= 0) {
return 0;
}
if (class_exists('\AKSRT\Settings\Settings') && !\AKSRT\Settings\Settings::notification_user_badge_enabled()) {
if (class_exists('\Jio\Settings\Settings') && !\Jio\Settings\Settings::notification_user_badge_enabled()) {
return 0;
}
$count = aksrt_get_user_unread_notification_count($user_id);
if (class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::notification_badge_include_stateful()) {
$count += aksrt_get_user_notification_count($user_id);
$count = jio_get_user_unread_notification_count($user_id);
if (class_exists('\Jio\Settings\Settings') && \Jio\Settings\Settings::notification_badge_include_stateful()) {
$count += jio_get_user_notification_count($user_id);
}
return $count;
}
endif;
if (!function_exists('aksrt_get_user_all_notifications')) :
if (!function_exists('jio_get_user_all_notifications')) :
/** 获取用户完整通知列表(持久化通知 + 即时提醒) */
function aksrt_get_user_all_notifications(int $user_id = 0): array {
function jio_get_user_all_notifications(int $user_id = 0): array {
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
if ($user_id <= 0) return [];
$inbox = aksrt_get_user_inbox_notifications($user_id);
$alerts = aksrt_get_user_notifications($user_id);
$inbox = jio_get_user_inbox_notifications($user_id);
$alerts = jio_get_user_notifications($user_id);
$normalized_alerts = [];
foreach ($alerts as $alert) {
@@ -336,100 +336,100 @@ function aksrt_get_user_all_notifications(int $user_id = 0): array {
}
endif;
add_action('wp_ajax_aksrt_mark_notification_read', function () {
add_action('wp_ajax_jio_mark_notification_read', function () {
if (!is_user_logged_in()) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')], 401);
wp_send_json_error(['message' => __('请先登录', 'jio')], 401);
}
$nonce = isset($_POST['nonce']) ? (string) $_POST['nonce'] : '';
if (!wp_verify_nonce($nonce, 'aksrt_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'aksrt')], 403);
if (!wp_verify_nonce($nonce, 'jio_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'jio')], 403);
}
$notification_id = sanitize_text_field((string) ($_POST['notification_id'] ?? ''));
$mark_all = !empty($_POST['mark_all']);
aksrt_mark_user_notification_read(get_current_user_id(), $notification_id, $mark_all);
jio_mark_user_notification_read(get_current_user_id(), $notification_id, $mark_all);
wp_send_json_success([
'unread' => aksrt_get_user_unread_notification_count(get_current_user_id()),
'unread' => jio_get_user_unread_notification_count(get_current_user_id()),
]);
});
add_action('wp_ajax_aksrt_delete_notification', function () {
add_action('wp_ajax_jio_delete_notification', function () {
if (!is_user_logged_in()) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')], 401);
wp_send_json_error(['message' => __('请先登录', 'jio')], 401);
}
$nonce = isset($_POST['nonce']) ? (string) $_POST['nonce'] : '';
if (!wp_verify_nonce($nonce, 'aksrt_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'aksrt')], 403);
if (!wp_verify_nonce($nonce, 'jio_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'jio')], 403);
}
$notification_id = sanitize_text_field((string) ($_POST['notification_id'] ?? ''));
if ($notification_id === '') {
wp_send_json_error(['message' => __('参数错误', 'aksrt')], 400);
wp_send_json_error(['message' => __('参数错误', 'jio')], 400);
}
aksrt_delete_user_notification(get_current_user_id(), $notification_id);
jio_delete_user_notification(get_current_user_id(), $notification_id);
wp_send_json_success([
'unread' => aksrt_get_user_unread_notification_count(get_current_user_id()),
'unread' => jio_get_user_unread_notification_count(get_current_user_id()),
]);
});
add_action('wp_ajax_aksrt_delete_notifications', function () {
add_action('wp_ajax_jio_delete_notifications', function () {
if (!is_user_logged_in()) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')], 401);
wp_send_json_error(['message' => __('请先登录', 'jio')], 401);
}
$nonce = isset($_POST['nonce']) ? (string) $_POST['nonce'] : '';
if (!wp_verify_nonce($nonce, 'aksrt_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'aksrt')], 403);
if (!wp_verify_nonce($nonce, 'jio_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'jio')], 403);
}
$ids = isset($_POST['notification_ids']) ? (array) $_POST['notification_ids'] : [];
aksrt_delete_user_notifications(get_current_user_id(), $ids);
jio_delete_user_notifications(get_current_user_id(), $ids);
wp_send_json_success([
'unread' => aksrt_get_user_unread_notification_count(get_current_user_id()),
'unread' => jio_get_user_unread_notification_count(get_current_user_id()),
]);
});
add_action('wp_ajax_aksrt_check_new_notifications', function () {
add_action('wp_ajax_jio_check_new_notifications', function () {
if (!is_user_logged_in()) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')], 401);
wp_send_json_error(['message' => __('请先登录', 'jio')], 401);
}
$nonce = isset($_POST['nonce']) ? (string) $_POST['nonce'] : '';
if (!wp_verify_nonce($nonce, 'aksrt_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'aksrt')], 403);
if (!wp_verify_nonce($nonce, 'jio_public_nonce')) {
wp_send_json_error(['message' => __('安全验证失败', 'jio')], 403);
}
$counts = function_exists('aksrt_get_message_center_counts') ? aksrt_get_message_center_counts(get_current_user_id()) : [];
$unread = isset($counts['unread']) ? (int) $counts['unread'] : aksrt_get_user_unread_notification_count(get_current_user_id());
$counts = function_exists('jio_get_message_center_counts') ? jio_get_message_center_counts(get_current_user_id()) : [];
$unread = isset($counts['unread']) ? (int) $counts['unread'] : jio_get_user_unread_notification_count(get_current_user_id());
wp_send_json_success([
'count' => $unread,
'unread' => $unread,
]);
});
function aksrt_notify_post_author_of_comment(WP_Comment $comment): void {
if ((int) $comment->comment_parent > 0 || get_comment_meta($comment->comment_ID, 'aksrt_post_comment_notified', true)) return;
function jio_notify_post_author_of_comment(WP_Comment $comment): void {
if ((int) $comment->comment_parent > 0 || get_comment_meta($comment->comment_ID, 'jio_post_comment_notified', true)) return;
$post = get_post((int) $comment->comment_post_ID);
$owner_id = $post instanceof WP_Post ? (int) $post->post_author : 0;
if ($owner_id <= 0 || $owner_id === (int) $comment->user_id) return;
aksrt_add_user_notification($owner_id, [
jio_add_user_notification($owner_id, [
'type' => 'comment',
'title' => __('文章收到评论', 'aksrt'),
'desc' => sprintf(__('%1$s 评论了你的文章《%2$s》。', 'aksrt'), get_comment_author($comment), get_the_title($post)),
'title' => __('文章收到评论', 'jio'),
'desc' => sprintf(__('%1$s 评论了你的文章《%2$s》。', 'jio'), get_comment_author($comment), get_the_title($post)),
'url' => get_comment_link($comment),
]);
update_comment_meta($comment->comment_ID, 'aksrt_post_comment_notified', 1);
update_comment_meta($comment->comment_ID, 'jio_post_comment_notified', 1);
}
add_action('wp_insert_comment', function ($comment_id, $comment) {
if (!$comment instanceof WP_Comment) return;
if ((int) $comment->comment_approved !== 1) return;
aksrt_notify_post_author_of_comment($comment);
jio_notify_post_author_of_comment($comment);
if ((int) $comment->comment_parent <= 0) return;
if (get_comment_meta($comment_id, 'aksrt_reply_notified', true)) return;
if (get_comment_meta($comment_id, 'jio_reply_notified', true)) return;
$parent = get_comment((int) $comment->comment_parent);
if (!$parent instanceof WP_Comment) return;
@@ -438,13 +438,13 @@ add_action('wp_insert_comment', function ($comment_id, $comment) {
$post_id = (int) $comment->comment_post_ID;
$url = get_comment_link($comment);
aksrt_add_user_notification($target_user_id, [
jio_add_user_notification($target_user_id, [
'type' => 'comment_reply',
'title' => __('评论收到回复', 'aksrt'),
'desc' => sprintf(__('“%s” 回复了你的评论。', 'aksrt'), get_comment_author($comment)),
'title' => __('评论收到回复', 'jio'),
'desc' => sprintf(__('“%s” 回复了你的评论。', 'jio'), get_comment_author($comment)),
'url' => $url ?: get_permalink($post_id),
]);
update_comment_meta($comment_id, 'aksrt_reply_notified', 1);
update_comment_meta($comment_id, 'jio_reply_notified', 1);
}, 20, 2);
add_action('transition_comment_status', function ($new_status, $old_status, $comment) {
@@ -452,81 +452,81 @@ add_action('transition_comment_status', function ($new_status, $old_status, $com
if ($new_status !== 'approve' || $old_status === 'approve') return;
$comment_owner_id = (int) $comment->user_id;
if ($comment_owner_id > 0 && !get_comment_meta($comment->comment_ID, 'aksrt_approved_notified', true)) {
aksrt_add_user_notification($comment_owner_id, [
if ($comment_owner_id > 0 && !get_comment_meta($comment->comment_ID, 'jio_approved_notified', true)) {
jio_add_user_notification($comment_owner_id, [
'type' => 'comment_approved',
'title' => __('评论已通过审核', 'aksrt'),
'desc' => __('你的评论已通过审核,现已公开展示。', 'aksrt'),
'title' => __('评论已通过审核', 'jio'),
'desc' => __('你的评论已通过审核,现已公开展示。', 'jio'),
'url' => get_comment_link($comment),
]);
update_comment_meta($comment->comment_ID, 'aksrt_approved_notified', 1);
update_comment_meta($comment->comment_ID, 'jio_approved_notified', 1);
}
aksrt_notify_post_author_of_comment($comment);
jio_notify_post_author_of_comment($comment);
if ((int) $comment->comment_parent <= 0) return;
if (get_comment_meta($comment->comment_ID, 'aksrt_reply_notified', true)) return;
if (get_comment_meta($comment->comment_ID, 'jio_reply_notified', true)) return;
$parent = get_comment((int) $comment->comment_parent);
if (!$parent instanceof WP_Comment) return;
$target_user_id = (int) $parent->user_id;
if ($target_user_id <= 0 || $target_user_id === (int) $comment->user_id) return;
aksrt_add_user_notification($target_user_id, [
jio_add_user_notification($target_user_id, [
'type' => 'comment_reply',
'title' => __('评论收到回复', 'aksrt'),
'desc' => sprintf(__('“%s” 回复了你的评论。', 'aksrt'), get_comment_author($comment)),
'title' => __('评论收到回复', 'jio'),
'desc' => sprintf(__('“%s” 回复了你的评论。', 'jio'), get_comment_author($comment)),
'url' => get_comment_link($comment),
]);
update_comment_meta($comment->comment_ID, 'aksrt_reply_notified', 1);
update_comment_meta($comment->comment_ID, 'jio_reply_notified', 1);
}, 20, 3);
add_action('aksrt_post_favorited', function (int $post_id, int $actor_id, bool $active): void {
add_action('jio_post_favorited', function (int $post_id, int $actor_id, bool $active): void {
$post = $active ? get_post($post_id) : null;
$owner_id = $post instanceof WP_Post ? (int) $post->post_author : 0;
if ($owner_id <= 0 || $owner_id === $actor_id) return;
$actor = get_userdata($actor_id);
aksrt_add_user_notification($owner_id, [
jio_add_user_notification($owner_id, [
'type' => 'post_favorite',
'title' => __('文章被收藏', 'aksrt'),
'desc' => sprintf(__('%1$s 收藏了你的文章《%2$s》。', 'aksrt'), $actor instanceof WP_User ? $actor->display_name : __('一位用户', 'aksrt'), get_the_title($post)),
'title' => __('文章被收藏', 'jio'),
'desc' => sprintf(__('%1$s 收藏了你的文章《%2$s》。', 'jio'), $actor instanceof WP_User ? $actor->display_name : __('一位用户', 'jio'), get_the_title($post)),
'url' => get_permalink($post),
]);
}, 30, 3);
add_action('aksrt_post_liked', function (int $post_id, int $actor_id, bool $active): void {
add_action('jio_post_liked', function (int $post_id, int $actor_id, bool $active): void {
$post = $active ? get_post($post_id) : null;
$owner_id = $post instanceof WP_Post ? (int) $post->post_author : 0;
if ($owner_id <= 0 || $owner_id === $actor_id) return;
$actor = get_userdata($actor_id);
aksrt_add_user_notification($owner_id, [
jio_add_user_notification($owner_id, [
'type' => 'post_like',
'title' => __('文章收到点赞', 'aksrt'),
'desc' => sprintf(__('%1$s 点赞了你的文章《%2$s》。', 'aksrt'), $actor instanceof WP_User ? $actor->display_name : __('一位用户', 'aksrt'), get_the_title($post)),
'title' => __('文章收到点赞', 'jio'),
'desc' => sprintf(__('%1$s 点赞了你的文章《%2$s》。', 'jio'), $actor instanceof WP_User ? $actor->display_name : __('一位用户', 'jio'), get_the_title($post)),
'url' => get_permalink($post),
]);
}, 30, 3);
add_action('aksrt_comment_liked', function (int $comment_id, int $actor_id, bool $active): void {
add_action('jio_comment_liked', function (int $comment_id, int $actor_id, bool $active): void {
$comment = $active ? get_comment($comment_id) : null;
$owner_id = $comment instanceof WP_Comment ? (int) $comment->user_id : 0;
if ($owner_id <= 0 || $owner_id === $actor_id) return;
$actor = get_userdata($actor_id);
aksrt_add_user_notification($owner_id, [
jio_add_user_notification($owner_id, [
'type' => 'comment_like',
'title' => __('评论收到点赞', 'aksrt'),
'desc' => sprintf(__('%s 点赞了你的评论。', 'aksrt'), $actor instanceof WP_User ? $actor->display_name : __('一位用户', 'aksrt')),
'title' => __('评论收到点赞', 'jio'),
'desc' => sprintf(__('%s 点赞了你的评论。', 'jio'), $actor instanceof WP_User ? $actor->display_name : __('一位用户', 'jio')),
'url' => get_comment_link($comment),
]);
}, 30, 3);
add_action('aksrt_user_followed', function (int $follower_id, int $following_id): void {
add_action('jio_user_followed', function (int $follower_id, int $following_id): void {
if ($following_id <= 0 || $following_id === $follower_id) return;
$follower = get_userdata($follower_id);
aksrt_add_user_notification($following_id, [
jio_add_user_notification($following_id, [
'type' => 'followed',
'title' => __('收到新的关注', 'aksrt'),
'desc' => sprintf(__('%s 关注了你。', 'aksrt'), $follower instanceof WP_User ? $follower->display_name : __('一位用户', 'aksrt')),
'url' => function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($follower_id) : '',
'title' => __('收到新的关注', 'jio'),
'desc' => sprintf(__('%s 关注了你。', 'jio'), $follower instanceof WP_User ? $follower->display_name : __('一位用户', 'jio')),
'url' => function_exists('jio_get_user_home_url') ? jio_get_user_home_url($follower_id) : '',
]);
}, 30, 2);
+115 -115
View File
@@ -2,48 +2,48 @@
/** User profile and account settings AJAX handlers. */
defined('ABSPATH') || exit;
if (!function_exists('aksrt_account_captcha_error_data')) {
function aksrt_account_captcha_error_data($result): array {
if (!function_exists('jio_account_captcha_error_data')) {
function jio_account_captcha_error_data($result): array {
return [
'code' => is_wp_error($result) ? ($result->get_error_code() ?: 'aksrt_captcha_failed') : 'aksrt_captcha_failed',
'code' => is_wp_error($result) ? ($result->get_error_code() ?: 'jio_captcha_failed') : 'jio_captcha_failed',
'message' => is_wp_error($result)
? ($result->get_error_message() ?: __('人机验证失败,请重试', 'aksrt'))
: __('人机验证失败,请重试', 'aksrt'),
? ($result->get_error_message() ?: __('人机验证失败,请重试', 'jio'))
: __('人机验证失败,请重试', 'jio'),
];
}
}
add_action('wp_ajax_aksrt_save_profile', function (): void {
add_action('wp_ajax_jio_save_profile', function (): void {
if (
!isset($_POST['_profile_nonce'])
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_profile_nonce'])), 'aksrt_profile_save')
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_profile_nonce'])), 'jio_profile_save')
) {
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]);
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'jio')]);
}
$user_id = (int) ($_POST['user_id'] ?? 0);
$result = function_exists('aksrt_save_user_center_profile')
? aksrt_save_user_center_profile($user_id, $_POST)
: new WP_Error('aksrt_profile_unavailable', __('保存失败', 'aksrt'));
$result = function_exists('jio_save_user_center_profile')
? jio_save_user_center_profile($user_id, $_POST)
: new WP_Error('jio_profile_unavailable', __('保存失败', 'jio'));
if (is_wp_error($result)) wp_send_json_error(['message' => $result->get_error_message()]);
wp_send_json_success(['message' => __('保存成功!', 'aksrt')]);
wp_send_json_success(['message' => __('保存成功!', 'jio')]);
});
function aksrt_account_code_key(int $user_id, string $scene, string $target): string {
return 'aksrt_account_code_' . $user_id . '_' . sanitize_key($scene) . '_' . md5(strtolower(trim($target)));
function jio_account_code_key(int $user_id, string $scene, string $target): string {
return 'jio_account_code_' . $user_id . '_' . sanitize_key($scene) . '_' . md5(strtolower(trim($target)));
}
function aksrt_account_store_code(int $user_id, string $scene, string $target, string $code): void {
function jio_account_store_code(int $user_id, string $scene, string $target, string $code): void {
set_transient(
aksrt_account_code_key($user_id, $scene, $target),
jio_account_code_key($user_id, $scene, $target),
['hash' => wp_hash_password($code), 'attempts' => 0],
5 * MINUTE_IN_SECONDS
);
}
function aksrt_account_consume_code(int $user_id, string $scene, string $target, string $code, bool $consume = true): bool {
$key = aksrt_account_code_key($user_id, $scene, $target);
function jio_account_consume_code(int $user_id, string $scene, string $target, string $code, bool $consume = true): bool {
$key = jio_account_code_key($user_id, $scene, $target);
$stored = get_transient($key);
if (!is_array($stored) || empty($stored['hash'])) {
return false;
@@ -67,20 +67,20 @@ function aksrt_account_consume_code(int $user_id, string $scene, string $target,
return true;
}
function aksrt_account_proof_key(int $user_id, string $kind): string {
return 'aksrt_account_proof_' . sanitize_key($kind) . '_' . $user_id;
function jio_account_proof_key(int $user_id, string $kind): string {
return 'jio_account_proof_' . sanitize_key($kind) . '_' . $user_id;
}
function aksrt_account_set_proof(int $user_id, string $kind, string $target): void {
function jio_account_set_proof(int $user_id, string $kind, string $target): void {
set_transient(
aksrt_account_proof_key($user_id, $kind),
jio_account_proof_key($user_id, $kind),
['target' => strtolower(trim($target))],
30 * MINUTE_IN_SECONDS
);
}
function aksrt_account_consume_proof(int $user_id, string $kind, string $target, bool $consume = true): bool {
$key = aksrt_account_proof_key($user_id, $kind);
function jio_account_consume_proof(int $user_id, string $kind, string $target, bool $consume = true): bool {
$key = jio_account_proof_key($user_id, $kind);
$proof = get_transient($key);
if (!is_array($proof) || strtolower(trim((string) ($proof['target'] ?? ''))) !== strtolower(trim($target))) {
return false;
@@ -92,170 +92,170 @@ function aksrt_account_consume_proof(int $user_id, string $kind, string $target,
return true;
}
function aksrt_account_email_verification_required(): bool {
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
function jio_account_email_verification_required(): bool {
$settings = class_exists('\Jio\Settings\Settings') ? \Jio\Settings\Settings::get_all() : [];
return !empty($settings['email_set_captch']);
}
add_action('wp_ajax_aksrt_send_account_email_code', function (): void {
add_action('wp_ajax_jio_send_account_email_code', function (): void {
if (
!isset($_POST['_settings_nonce'])
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings')
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'jio_account_settings')
) {
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]);
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'jio')]);
}
$user_id = get_current_user_id();
$user = wp_get_current_user();
if (!$user_id || !($user instanceof WP_User)) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
wp_send_json_error(['message' => __('请先登录', 'jio')]);
}
$scene = sanitize_key((string) wp_unslash($_POST['scene'] ?? ''));
if (!in_array($scene, ['verify_email', 'change_email'], true)) {
wp_send_json_error(['message' => __('无效的验证场景', 'aksrt')]);
wp_send_json_error(['message' => __('无效的验证场景', 'jio')]);
}
if (!aksrt_account_email_verification_required()) {
wp_send_json_error(['message' => __('邮箱验证码验证未开启', 'aksrt')]);
if (!jio_account_email_verification_required()) {
wp_send_json_error(['message' => __('邮箱验证码验证未开启', 'jio')]);
}
$target = $scene === 'verify_email'
? (string) $user->user_email
: sanitize_email((string) wp_unslash($_POST['new_email'] ?? ''));
if (!is_email($target)) {
wp_send_json_error(['message' => __('邮箱格式错误', 'aksrt')]);
wp_send_json_error(['message' => __('邮箱格式错误', 'jio')]);
}
if ($scene === 'change_email') {
if (strtolower($target) === strtolower((string) $user->user_email)) {
wp_send_json_error(['message' => __('修改邮箱不能与现邮箱相同', 'aksrt')]);
wp_send_json_error(['message' => __('修改邮箱不能与现邮箱相同', 'jio')]);
}
if (email_exists($target)) {
wp_send_json_error(['message' => __('该邮箱已有绑定账号', 'aksrt')]);
wp_send_json_error(['message' => __('该邮箱已有绑定账号', 'jio')]);
}
}
if (function_exists('aksrt_require_captcha')) {
$captcha = aksrt_require_captcha('change_email', wp_unslash($_POST));
if (function_exists('jio_require_captcha')) {
$captcha = jio_require_captcha('change_email', wp_unslash($_POST));
if ($captcha !== true) {
wp_send_json_error(aksrt_account_captcha_error_data($captcha));
wp_send_json_error(jio_account_captcha_error_data($captcha));
}
}
if (class_exists('\AKSRT\Extensions\SendLimit')) {
$limit = \AKSRT\Extensions\SendLimit::check($target);
if (class_exists('\Jio\Extensions\SendLimit')) {
$limit = \Jio\Extensions\SendLimit::check($target);
if (empty($limit['ok'])) {
wp_send_json_error(['message' => (string) $limit['message']]);
}
}
$code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
$sent = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::send_event_email('change_code', $target, [
$sent = class_exists('\Jio\Settings\Settings')
? \Jio\Settings\Settings::send_event_email('change_code', $target, [
'{username}' => $user->display_name,
'{site_name}' => get_bloginfo('name'),
'{code}' => $code,
])
: false;
if (!$sent) {
wp_send_json_error(['message' => __('验证码邮件发送失败,请稍后重试', 'aksrt')]);
wp_send_json_error(['message' => __('验证码邮件发送失败,请稍后重试', 'jio')]);
}
$cooldown = class_exists('\AKSRT\Extensions\SendLimit') ? (int) \AKSRT\Extensions\SendLimit::record($target) : 0;
aksrt_account_store_code($user_id, $scene, $target, $code);
$cooldown = class_exists('\Jio\Extensions\SendLimit') ? (int) \Jio\Extensions\SendLimit::record($target) : 0;
jio_account_store_code($user_id, $scene, $target, $code);
wp_send_json_success([
'message' => $scene === 'verify_email'
? __('验证码已发送到您的老邮箱', 'aksrt')
: __('验证码已发送到新邮箱', 'aksrt'),
? __('验证码已发送到您的老邮箱', 'jio')
: __('验证码已发送到新邮箱', 'jio'),
'countdown' => $cooldown > 0 ? $cooldown : 60,
]);
});
add_action('wp_ajax_aksrt_verify_account_email', function (): void {
add_action('wp_ajax_jio_verify_account_email', function (): void {
if (
!isset($_POST['_settings_nonce'])
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings')
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'jio_account_settings')
) {
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]);
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'jio')]);
}
$user_id = get_current_user_id();
$user = wp_get_current_user();
if (!$user_id || !($user instanceof WP_User) || !is_email((string) $user->user_email)) {
wp_send_json_error(['message' => __('当前账号未绑定有效邮箱', 'aksrt')]);
wp_send_json_error(['message' => __('当前账号未绑定有效邮箱', 'jio')]);
}
if (!aksrt_account_email_verification_required()) {
wp_send_json_error(['message' => __('邮箱验证码验证未开启', 'aksrt')]);
if (!jio_account_email_verification_required()) {
wp_send_json_error(['message' => __('邮箱验证码验证未开启', 'jio')]);
}
if (function_exists('aksrt_require_captcha')) {
$captcha = aksrt_require_captcha('change_email', wp_unslash($_POST));
if (function_exists('jio_require_captcha')) {
$captcha = jio_require_captcha('change_email', wp_unslash($_POST));
if ($captcha !== true) {
wp_send_json_error(aksrt_account_captcha_error_data($captcha));
wp_send_json_error(jio_account_captcha_error_data($captcha));
}
}
$code = sanitize_text_field((string) wp_unslash($_POST['code'] ?? ''));
if (!aksrt_account_consume_code($user_id, 'verify_email', (string) $user->user_email, $code)) {
if (class_exists('\AKSRT\Extensions\SecurityHardening')) {
\AKSRT\Extensions\SecurityHardening::error_frequency_record();
if (!jio_account_consume_code($user_id, 'verify_email', (string) $user->user_email, $code)) {
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::error_frequency_record();
}
wp_send_json_error(['message' => __('验证码错误或已过期', 'aksrt')]);
wp_send_json_error(['message' => __('验证码错误或已过期', 'jio')]);
}
if (class_exists('\AKSRT\Extensions\SecurityHardening')) {
\AKSRT\Extensions\SecurityHardening::error_frequency_clear();
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::error_frequency_clear();
}
aksrt_account_set_proof($user_id, 'email_old', (string) $user->user_email);
wp_send_json_success(['message' => __('验证成功', 'aksrt')]);
jio_account_set_proof($user_id, 'email_old', (string) $user->user_email);
wp_send_json_success(['message' => __('验证成功', 'jio')]);
});
add_action('wp_ajax_aksrt_change_password', function (): void {
add_action('wp_ajax_jio_change_password', function (): void {
if (
!isset($_POST['_settings_nonce'])
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings')
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'jio_account_settings')
) {
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]);
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'jio')]);
}
$user_id = get_current_user_id();
if (!$user_id) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
wp_send_json_error(['message' => __('请先登录', 'jio')]);
}
$user = get_userdata($user_id);
if (!($user instanceof WP_User)) {
wp_send_json_error(['message' => __('账号信息读取失败,请刷新页面重试', 'aksrt')]);
wp_send_json_error(['message' => __('账号信息读取失败,请刷新页面重试', 'jio')]);
}
$oauth_new = (bool) get_user_meta($user_id, 'oauth_new', true);
$password = trim((string) wp_unslash($_POST['password'] ?? ''));
$password2 = trim((string) wp_unslash($_POST['password2'] ?? ''));
if (function_exists('aksrt_require_captcha')) {
$captcha = aksrt_require_captcha('change_password', wp_unslash($_POST));
if (function_exists('jio_require_captcha')) {
$captcha = jio_require_captcha('change_password', wp_unslash($_POST));
if ($captcha !== true) {
wp_send_json_error(aksrt_account_captcha_error_data($captcha));
wp_send_json_error(jio_account_captcha_error_data($captcha));
}
}
if (!$oauth_new) {
$old_password = trim((string) wp_unslash($_POST['passwordold'] ?? ''));
if ($old_password === '') {
wp_send_json_error(['message' => __('请输入原密码', 'aksrt')]);
wp_send_json_error(['message' => __('请输入原密码', 'jio')]);
}
if ($old_password === $password) {
wp_send_json_error(['message' => __('新密码和原密码不能相同', 'aksrt')]);
wp_send_json_error(['message' => __('新密码和原密码不能相同', 'jio')]);
}
if (class_exists('\AKSRT\Extensions\SecurityHardening') && ($wait = \AKSRT\Extensions\SecurityHardening::error_frequency_wait()) > 0) {
wp_send_json_error(['message' => sprintf(__('验证错误次数过多,请 %d 秒后再试', 'aksrt'), $wait)]);
if (class_exists('\Jio\Extensions\SecurityHardening') && ($wait = \Jio\Extensions\SecurityHardening::error_frequency_wait()) > 0) {
wp_send_json_error(['message' => sprintf(__('验证错误次数过多,请 %d 秒后再试', 'jio'), $wait)]);
}
if (!wp_check_password($old_password, $user->user_pass, $user_id)) {
if (class_exists('\AKSRT\Extensions\SecurityHardening')) {
\AKSRT\Extensions\SecurityHardening::error_frequency_record();
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::error_frequency_record();
}
wp_send_json_error(['message' => __('原密码错误', 'aksrt')]);
wp_send_json_error(['message' => __('原密码错误', 'jio')]);
}
}
$valid = class_exists('\AKSRT\Auth\Service')
? \AKSRT\Auth\Service::validate_password($password, $password2)
: __('认证服务不可用', 'aksrt');
$valid = class_exists('\Jio\Auth\Service')
? \Jio\Auth\Service::validate_password($password, $password2)
: __('认证服务不可用', 'jio');
if ($valid !== true) {
wp_send_json_error(['message' => (string) $valid]);
}
@@ -266,65 +266,65 @@ add_action('wp_ajax_aksrt_change_password', function (): void {
}
delete_user_meta($user_id, 'oauth_new');
if (class_exists('\AKSRT\Extensions\SecurityHardening')) {
\AKSRT\Extensions\SecurityHardening::error_frequency_clear();
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::error_frequency_clear();
}
wp_send_json_success([
'message' => $oauth_new
? __('密码设置成功', 'aksrt')
: __('修改成功,下次请使用新密码登录', 'aksrt'),
? __('密码设置成功', 'jio')
: __('修改成功,下次请使用新密码登录', 'jio'),
'reload' => true,
]);
});
add_action('wp_ajax_aksrt_change_email', function (): void {
add_action('wp_ajax_jio_change_email', function (): void {
if (
!isset($_POST['_settings_nonce'])
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings')
|| !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'jio_account_settings')
) {
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]);
wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'jio')]);
}
$user_id = get_current_user_id();
$user = wp_get_current_user();
if (!$user_id || !($user instanceof WP_User)) {
wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
wp_send_json_error(['message' => __('请先登录', 'jio')]);
}
$new_email = sanitize_email((string) wp_unslash($_POST['new_email'] ?? ''));
if (!is_email($new_email)) {
wp_send_json_error(['message' => __('邮箱格式错误', 'aksrt')]);
wp_send_json_error(['message' => __('邮箱格式错误', 'jio')]);
}
if ($user->user_email !== '' && strtolower($new_email) === strtolower((string) $user->user_email)) {
wp_send_json_error(['message' => __('修改邮箱不能与现邮箱相同', 'aksrt')]);
wp_send_json_error(['message' => __('修改邮箱不能与现邮箱相同', 'jio')]);
}
if (email_exists($new_email)) {
wp_send_json_error(['message' => __('该邮箱已有绑定账号', 'aksrt')]);
wp_send_json_error(['message' => __('该邮箱已有绑定账号', 'jio')]);
}
$agreement = function_exists('aksrt_get_auth_agreement_view') ? aksrt_get_auth_agreement_view() : ['enabled' => false, 'required' => false];
$agreement = function_exists('jio_get_auth_agreement_view') ? jio_get_auth_agreement_view() : ['enabled' => false, 'required' => false];
if (!empty($agreement['required']) && empty($_POST['agree_terms'])) {
wp_send_json_error(['message' => __('请先同意相关协议', 'aksrt')]);
wp_send_json_error(['message' => __('请先同意相关协议', 'jio')]);
}
if (function_exists('aksrt_require_captcha')) {
$captcha = aksrt_require_captcha('change_email', wp_unslash($_POST));
if (function_exists('jio_require_captcha')) {
$captcha = jio_require_captcha('change_email', wp_unslash($_POST));
if ($captcha !== true) {
wp_send_json_error(aksrt_account_captcha_error_data($captcha));
wp_send_json_error(jio_account_captcha_error_data($captcha));
}
}
$verification_required = aksrt_account_email_verification_required();
$verification_required = jio_account_email_verification_required();
$old_email = (string) $user->user_email;
if (
$old_email !== ''
&& $verification_required
&& !aksrt_account_consume_proof($user_id, 'email_old', $old_email, false)
&& !jio_account_consume_proof($user_id, 'email_old', $old_email, false)
) {
wp_send_json_error(['message' => __('请先验证老邮箱', 'aksrt')]);
wp_send_json_error(['message' => __('请先验证老邮箱', 'jio')]);
}
if (
$verification_required
&& !aksrt_account_consume_code(
&& !jio_account_consume_code(
$user_id,
'change_email',
$new_email,
@@ -332,29 +332,29 @@ add_action('wp_ajax_aksrt_change_email', function (): void {
false
)
) {
if (class_exists('\AKSRT\Extensions\SecurityHardening')) {
\AKSRT\Extensions\SecurityHardening::error_frequency_record();
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::error_frequency_record();
}
wp_send_json_error(['message' => __('验证码错误或已过期', 'aksrt')]);
wp_send_json_error(['message' => __('验证码错误或已过期', 'jio')]);
}
$result = wp_update_user(['ID' => $user_id, 'user_email' => $new_email]);
if (is_wp_error($result)) {
wp_send_json_error(['message' => $result->get_error_message() ?: __('邮箱更新失败,请稍后重试', 'aksrt')]);
wp_send_json_error(['message' => $result->get_error_message() ?: __('邮箱更新失败,请稍后重试', 'jio')]);
}
if ($old_email !== '' && $verification_required) {
delete_transient(aksrt_account_proof_key($user_id, 'email_old'));
delete_transient(jio_account_proof_key($user_id, 'email_old'));
}
if ($verification_required) {
delete_transient(aksrt_account_code_key($user_id, 'change_email', $new_email));
delete_transient(jio_account_code_key($user_id, 'change_email', $new_email));
}
if (class_exists('\AKSRT\Extensions\SecurityHardening')) {
\AKSRT\Extensions\SecurityHardening::error_frequency_clear();
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::error_frequency_clear();
}
update_user_meta($user_id, 'aksrt_email_verified', 1);
if ($old_email !== '' && is_email($old_email) && class_exists('\AKSRT\Settings\Settings')) {
\AKSRT\Settings\Settings::send_event_email('change_notice', $old_email, [
update_user_meta($user_id, 'jio_email_verified', 1);
if ($old_email !== '' && is_email($old_email) && class_exists('\Jio\Settings\Settings')) {
\Jio\Settings\Settings::send_event_email('change_notice', $old_email, [
'{username}' => $user->display_name,
'{site_name}' => get_bloginfo('name'),
'{new_email}' => $new_email,
@@ -362,7 +362,7 @@ add_action('wp_ajax_aksrt_change_email', function (): void {
}
wp_send_json_success([
'message' => $old_email !== '' ? __('邮箱修改成功', 'aksrt') : __('邮箱绑定成功', 'aksrt'),
'message' => $old_email !== '' ? __('邮箱修改成功', 'jio') : __('邮箱绑定成功', 'jio'),
'reload' => true,
]);
});
+57 -57
View File
@@ -2,7 +2,7 @@
/**
* User rewrite/routing/bootstrap flush + author redirects
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
@@ -13,10 +13,10 @@ defined('ABSPATH') || exit;
// --- 3a. /user/{昵称} 自定义重写 ---
add_filter('query_vars', function ($vars) {
$vars[] = 'aksrt_user_center';
$vars[] = 'aksrt_user_center_tab';
$vars[] = 'aksrt_author_identifier';
$vars[] = 'aksrt_message_view';
$vars[] = 'jio_user_center';
$vars[] = 'jio_user_center_tab';
$vars[] = 'jio_author_identifier';
$vars[] = 'jio_message_view';
return $vars;
});
@@ -32,7 +32,7 @@ add_action('template_redirect', function () {
nocache_headers();
return;
}
if (!get_query_var('aksrt_message_view') && is_page() && get_page_template_slug(get_queried_object_id()) === 'templates/pages/page-messages.php') {
if (!get_query_var('jio_message_view') && is_page() && get_page_template_slug(get_queried_object_id()) === 'templates/pages/page-messages.php') {
global $wp_query;
if ($wp_query instanceof WP_Query) { $wp_query->set_404(); }
status_header(404);
@@ -40,7 +40,7 @@ add_action('template_redirect', function () {
return;
}
$resolved_path = aksrt_get_current_special_template_path();
$resolved_path = jio_get_current_special_template_path();
if ($resolved_path === '') {
return;
}
@@ -56,13 +56,13 @@ add_action('template_redirect', function () {
if (is_admin() || wp_doing_ajax()) {
return;
}
$tab = (string) get_query_var('aksrt_user_center_tab');
$tab = (string) get_query_var('jio_user_center_tab');
if ($tab === '') {
return;
}
$tab = $tab === 'balance' ? 'credits' : sanitize_key($tab);
$allowed = class_exists('\\AKSRT\\User\\Center')
? array_keys(\AKSRT\User\Center::get_instance()->get_dashboard_tabs())
$allowed = class_exists('\\Jio\\User\\Center')
? array_keys(\Jio\User\Center::get_instance()->get_dashboard_tabs())
: ['profile', 'level', 'creator', 'posts', 'follow', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'revenue', 'msg', 'settings'];
if (!in_array($tab, $allowed, true)) {
global $wp_query;
@@ -73,34 +73,34 @@ add_action('template_redirect', function () {
}, 1);
add_action('init', function () {
add_rewrite_tag('%aksrt_user_center%', '([^&]+)');
add_rewrite_tag('%aksrt_user_center_tab%', '([^/]+)');
add_rewrite_tag('%aksrt_author_identifier%', '([^/]+)');
add_rewrite_tag('%aksrt_message_view%', '(unread|posts|like|system)');
$message_slug = preg_quote(aksrt_get_messages_rewrite_slug(), '#');
add_rewrite_rule('^' . $message_slug . '/?$', 'index.php?aksrt_message_view=unread', 'top');
add_rewrite_rule('^' . $message_slug . '/(posts|like|system)/?$', 'index.php?aksrt_message_view=$matches[1]', 'top');
add_rewrite_rule('^user/([a-z0-9_-]+)/?$', 'index.php?aksrt_user_center=1&aksrt_user_center_tab=$matches[1]', 'top');
add_rewrite_rule('^author/([^/]+)/?$', 'index.php?aksrt_author_identifier=$matches[1]', 'top');
add_rewrite_tag('%jio_user_center%', '([^&]+)');
add_rewrite_tag('%jio_user_center_tab%', '([^/]+)');
add_rewrite_tag('%jio_author_identifier%', '([^/]+)');
add_rewrite_tag('%jio_message_view%', '(unread|posts|like|system)');
$message_slug = preg_quote(jio_get_messages_rewrite_slug(), '#');
add_rewrite_rule('^' . $message_slug . '/?$', 'index.php?jio_message_view=unread', 'top');
add_rewrite_rule('^' . $message_slug . '/(posts|like|system)/?$', 'index.php?jio_message_view=$matches[1]', 'top');
add_rewrite_rule('^user/([a-z0-9_-]+)/?$', 'index.php?jio_user_center=1&jio_user_center_tab=$matches[1]', 'top');
add_rewrite_rule('^author/([^/]+)/?$', 'index.php?jio_author_identifier=$matches[1]', 'top');
});
// --- 3b. 统一模板拦截器(核心)---
// 拦截所有使用主题特殊模板的页面请求,确保正确加载
add_filter('template_include', function ($template) {
$resolved_path = aksrt_get_current_special_template_path();
$resolved_path = jio_get_current_special_template_path();
if ($resolved_path !== '') {
return $resolved_path;
}
// A) /user/{昵称} even if special-path helper returned empty (user missing → 404).
$identifier = (string) get_query_var('aksrt_author_identifier');
$identifier = (string) get_query_var('jio_author_identifier');
if ($identifier !== '') {
$user = function_exists('aksrt_resolve_public_user') ? aksrt_resolve_public_user($identifier) : null;
$user = function_exists('jio_resolve_public_user') ? jio_resolve_public_user($identifier) : null;
if ($user instanceof WP_User) {
$tpl = aksrt_locate_template_file('templates/pages/page-user-home.php');
$tpl = jio_locate_template_file('templates/pages/page-user-home.php');
if ($tpl) {
global $aksrt_profile_user;
$aksrt_profile_user = $user;
global $jio_profile_user;
$jio_profile_user = $user;
return $tpl;
}
}
@@ -122,7 +122,7 @@ add_filter('template_include', function ($template) {
$slug = (string) get_post_field('post_name', $page_id);
$page_template = get_post_meta($page_id, '_wp_page_template', true);
if (is_string($page_template) && strpos($page_template, 'templates/pages/') === 0) {
$tpl = aksrt_locate_template_file($page_template);
$tpl = jio_locate_template_file($page_template);
if ($tpl) {
return $tpl;
}
@@ -134,13 +134,13 @@ add_filter('template_include', function ($template) {
}, 99);
add_filter('template_include', function ($template) {
$resolved_path = aksrt_get_current_special_template_path();
$resolved_path = jio_get_current_special_template_path();
if ($resolved_path !== '') {
return $resolved_path;
}
if (get_query_var('aksrt_user_center')) {
$profile_template = aksrt_locate_template_file('templates/pages/page-profile.php');
if (get_query_var('jio_user_center')) {
$profile_template = jio_locate_template_file('templates/pages/page-profile.php');
if ($profile_template) {
return $profile_template;
}
@@ -150,13 +150,13 @@ add_filter('template_include', function ($template) {
$page_id = get_queried_object_id();
if ($page_id > 0) {
$page_template = get_post_meta($page_id, '_wp_page_template', true);
$resolved_template = aksrt_resolve_page_template_file(
$resolved_template = jio_resolve_page_template_file(
is_string($page_template) ? $page_template : '',
(string) get_post_field('post_name', $page_id)
);
if ($resolved_template !== '') {
$resolved_path = aksrt_locate_template_file($resolved_template);
$resolved_path = jio_locate_template_file($resolved_template);
if ($resolved_path) {
return $resolved_path;
}
@@ -171,26 +171,26 @@ add_filter('template_include', function ($template) {
// 四、自动维护 + flush
// ============================================================
add_action('init', function () {
global $_aksrt_special_templates;
global $_jio_special_templates;
// 后台/AJAX:检查并创建缺失页面(含 profile 用户中心)
$pages_bootstrapped = get_option('aksrt_template_pages_bootstrapped');
$requested_template_key = (!is_admin() && !wp_doing_ajax()) ? aksrt_get_requested_template_key() : '';
if (is_admin() || wp_doing_ajax() || $pages_bootstrapped !== AKSRT_VERSION) {
foreach ($_aksrt_special_templates as $key => $cfg) {
aksrt_ensure_template_page($key);
$pages_bootstrapped = get_option('jio_template_pages_bootstrapped');
$requested_template_key = (!is_admin() && !wp_doing_ajax()) ? jio_get_requested_template_key() : '';
if (is_admin() || wp_doing_ajax() || $pages_bootstrapped !== JIO_VERSION) {
foreach ($_jio_special_templates as $key => $cfg) {
jio_ensure_template_page($key);
}
if ($pages_bootstrapped !== AKSRT_VERSION) {
update_option('aksrt_template_pages_bootstrapped', AKSRT_VERSION);
if ($pages_bootstrapped !== JIO_VERSION) {
update_option('jio_template_pages_bootstrapped', JIO_VERSION);
}
} elseif ($requested_template_key !== '') {
aksrt_ensure_template_page($requested_template_key);
jio_ensure_template_page($requested_template_key);
}
// 统一 flush 检查 — bump when user-home rewrite / author override changes
$rewrite_version = AKSRT_VERSION . ':message-routing:' . aksrt_get_messages_rewrite_slug();
$flushed = get_option('aksrt_user_rules_flushed');
$rewrite_version = JIO_VERSION . ':message-routing:' . jio_get_messages_rewrite_slug();
$flushed = get_option('jio_user_rules_flushed');
$rules = get_option('rewrite_rules');
$need_flush = ($flushed !== $rewrite_version)
|| !is_array($rules)
@@ -206,37 +206,37 @@ add_action('init', function () {
if ($need_flush) {
flush_rewrite_rules(true);
update_option('aksrt_user_rules_flushed', $rewrite_version);
update_option('jio_user_rules_flushed', $rewrite_version);
}
});
// 页面变更时清缓存
add_action('save_post', function ($pid) { if (get_post_type($pid) === 'page') aksrt_clear_template_page_cache(); });
add_action('delete_post', function ($pid) { if (get_post_type($pid) === 'page') aksrt_clear_template_page_cache(); });
add_action('save_post', function ($pid) { if (get_post_type($pid) === 'page') jio_clear_template_page_cache(); });
add_action('delete_post', function ($pid) { if (get_post_type($pid) === 'page') jio_clear_template_page_cache(); });
// ============================================================
// 六、作者链接改写 — 强制覆盖 WP 默认 /author/{slug}/
// ============================================================
add_filter('author_link', function ($link, $author_id) {
$author_id = (int) $author_id;
if ($author_id > 0 && function_exists('aksrt_get_user_home_url')) {
return aksrt_get_user_home_url($author_id);
if ($author_id > 0 && function_exists('jio_get_user_home_url')) {
return jio_get_user_home_url($author_id);
}
$user = get_userdata($author_id);
$slug = $user ? $user->user_nicename : ('user-' . max(0, $author_id));
if (!get_option('permalink_structure')) {
return add_query_arg('aksrt_author', rawurlencode($slug), home_url('/'));
return add_query_arg('jio_author', rawurlencode($slug), home_url('/'));
}
return home_url('/author/' . trailingslashit($slug));
}, 99, 2);
// Accept ?user_nicename= when pretty rewrites are unavailable.
add_filter('request', function ($query_vars) {
if (empty($query_vars['aksrt_author_identifier']) && !empty($_GET['aksrt_author'])) {
$query_vars['aksrt_author_identifier'] = sanitize_text_field(wp_unslash((string) $_GET['aksrt_author']));
if (empty($query_vars['jio_author_identifier']) && !empty($_GET['jio_author'])) {
$query_vars['jio_author_identifier'] = sanitize_text_field(wp_unslash((string) $_GET['jio_author']));
}
if (empty($query_vars['aksrt_user_center']) && isset($_GET['aksrt_user_center'])) {
$query_vars['aksrt_user_center'] = '1';
if (empty($query_vars['jio_user_center']) && isset($_GET['jio_user_center'])) {
$query_vars['jio_user_center'] = '1';
}
return $query_vars;
});
@@ -256,8 +256,8 @@ add_action('template_redirect', function () {
if ($author_id <= 0) {
return;
}
$target = function_exists('aksrt_get_user_home_url')
? aksrt_get_user_home_url($author_id)
$target = function_exists('jio_get_user_home_url')
? jio_get_user_home_url($author_id)
: home_url('/user/');
if ($target === '' || $target === home_url('/')) {
return;
@@ -274,15 +274,15 @@ add_action('template_redirect', function () {
if (empty($_GET['author'])) {
return;
}
if (get_query_var('aksrt_author_identifier') || get_query_var('aksrt_user_center')) {
if (get_query_var('jio_author_identifier') || get_query_var('jio_user_center')) {
return;
}
if (is_author()) {
return; // handled above
}
$author_id = (int) $_GET['author'];
if ($author_id > 0 && function_exists('aksrt_get_user_home_url')) {
wp_safe_redirect(aksrt_get_user_home_url($author_id), 301);
if ($author_id > 0 && function_exists('jio_get_user_home_url')) {
wp_safe_redirect(jio_get_user_home_url($author_id), 301);
exit;
}
}, 2);
+52 -52
View File
@@ -2,7 +2,7 @@
/**
* User template registry + template utils
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
@@ -12,7 +12,7 @@ defined('ABSPATH') || exit;
// 修改此处即可增删模板页面,无需改动其他逻辑
// ============================================================
// Only true fixed template pages live in the registry.
$_aksrt_special_templates = [
$_jio_special_templates = [
'sign' => [
'file' => 'templates/pages/page-sign.php',
'slug' => 'sign',
@@ -46,7 +46,7 @@ $_aksrt_special_templates = [
];
/** @var array 缓存 key=模板文件路径 => value=WP_Post|null */
$_aksrt_template_page_cache = [];
$_jio_template_page_cache = [];
// ============================================================
@@ -59,10 +59,10 @@ $_aksrt_template_page_cache = [];
* @param string $template_file 相对于主题的模板路径
* @return WP_Post|null
*/
function aksrt_find_template_page(string $template_file) {
global $_aksrt_template_page_cache;
if (isset($_aksrt_template_page_cache[$template_file])) {
return $_aksrt_template_page_cache[$template_file];
function jio_find_template_page(string $template_file) {
global $_jio_template_page_cache;
if (isset($_jio_template_page_cache[$template_file])) {
return $_jio_template_page_cache[$template_file];
}
$page = null;
@@ -76,7 +76,7 @@ function aksrt_find_template_page(string $template_file) {
$page = $pages[0];
}
$_aksrt_template_page_cache[$template_file] = $page;
$_jio_template_page_cache[$template_file] = $page;
return $page;
}
@@ -86,18 +86,18 @@ function aksrt_find_template_page(string $template_file) {
* @param string $key 注册表 key(当前仅 profile 使用)
* @return string 页面 URL 或回退地址
*/
function aksrt_get_template_url(string $key): string {
global $_aksrt_special_templates;
if (!isset($_aksrt_special_templates[$key])) {
function jio_get_template_url(string $key): string {
global $_jio_special_templates;
if (!isset($_jio_special_templates[$key])) {
return home_url('/');
}
$cfg = $_aksrt_special_templates[$key];
$page = aksrt_find_template_page($cfg['file']);
$cfg = $_jio_special_templates[$key];
$page = jio_find_template_page($cfg['file']);
if (!$page) {
aksrt_ensure_template_page($key);
$page = aksrt_find_template_page($cfg['file']);
jio_ensure_template_page($key);
$page = jio_find_template_page($cfg['file']);
}
if ($page) {
@@ -113,18 +113,18 @@ function aksrt_get_template_url(string $key): string {
* @param string $template_file 相对于主题的路径
* @return string|false 文件绝对路径或 false
*/
function aksrt_locate_template_file(string $template_file) {
function jio_locate_template_file(string $template_file) {
$path = locate_template([$template_file]);
if ($path) return $path;
$full = AKSRT_DIR . '/' . $template_file;
$full = JIO_DIR . '/' . $template_file;
return file_exists($full) ? $full : false;
}
/**
* Resolve a public-facing page template file from stored meta or page slug.
*/
function aksrt_resolve_page_template_file(string $template_file = '', string $post_slug = ''): string {
function jio_resolve_page_template_file(string $template_file = '', string $post_slug = ''): string {
$template_file = ltrim($template_file, '/\\');
$post_slug = sanitize_title($post_slug);
@@ -136,7 +136,7 @@ function aksrt_resolve_page_template_file(string $template_file = '', string $po
return $template_file;
}
if (strpos($template_file, 'templates/pages/') === 0 && aksrt_locate_template_file($template_file)) {
if (strpos($template_file, 'templates/pages/') === 0 && jio_locate_template_file($template_file)) {
return $template_file;
}
}
@@ -152,7 +152,7 @@ function aksrt_resolve_page_template_file(string $template_file = '', string $po
'profile' => 'templates/pages/page-profile.php',
];
if (!empty($slug_map[$post_slug]) && aksrt_locate_template_file($slug_map[$post_slug])) {
if (!empty($slug_map[$post_slug]) && jio_locate_template_file($slug_map[$post_slug])) {
return $slug_map[$post_slug];
}
}
@@ -163,7 +163,7 @@ function aksrt_resolve_page_template_file(string $template_file = '', string $po
/**
* Normalize auth view keys used by the unified sign page.
*/
function aksrt_normalize_auth_tab(string $tab): string {
function jio_normalize_auth_tab(string $tab): string {
$tab = sanitize_key($tab);
switch ($tab) {
@@ -185,57 +185,57 @@ function aksrt_normalize_auth_tab(string $tab): string {
/**
* 清除模板页面缓存
*/
function aksrt_clear_template_page_cache(): void {
global $_aksrt_template_page_cache;
$_aksrt_template_page_cache = [];
function jio_clear_template_page_cache(): void {
global $_jio_template_page_cache;
$_jio_template_page_cache = [];
}
/**
* Prepare the public user-home template context and return its template path.
*/
function aksrt_get_user_home_template_path(): string {
global $_aksrt_special_templates, $aksrt_profile_user;
function jio_get_user_home_template_path(): string {
global $_jio_special_templates, $jio_profile_user;
$identifier = (string) get_query_var('aksrt_author_identifier');
$identifier = (string) get_query_var('jio_author_identifier');
if ($identifier === '') {
return '';
}
$user = function_exists('aksrt_resolve_public_user') ? aksrt_resolve_public_user($identifier) : null;
$user = function_exists('jio_resolve_public_user') ? jio_resolve_public_user($identifier) : null;
if (!$user instanceof WP_User) {
return '';
}
$template_path = aksrt_locate_template_file('templates/pages/page-user-home.php');
$template_path = jio_locate_template_file('templates/pages/page-user-home.php');
if (!$template_path) {
return '';
}
$aksrt_profile_user = $user;
$jio_profile_user = $user;
return $template_path;
}
/**
* Resolve the active special-page template path for the current request.
*/
function aksrt_get_current_special_template_path(): string {
if (get_query_var('aksrt_message_view')) {
$message_template = aksrt_locate_template_file('templates/pages/page-messages.php');
function jio_get_current_special_template_path(): string {
if (get_query_var('jio_message_view')) {
$message_template = jio_locate_template_file('templates/pages/page-messages.php');
return $message_template ?: '';
}
if (get_query_var('aksrt_author_identifier')) {
return aksrt_get_user_home_template_path();
if (get_query_var('jio_author_identifier')) {
return jio_get_user_home_template_path();
}
if (get_query_var('aksrt_user_center')) {
$profile_template = aksrt_locate_template_file('templates/pages/page-profile.php');
if (get_query_var('jio_user_center')) {
$profile_template = jio_locate_template_file('templates/pages/page-profile.php');
return $profile_template ?: '';
}
if (get_query_var('aksrt_sign')) {
$auth_template_path = aksrt_locate_template_file('templates/pages/page-sign.php');
if (get_query_var('jio_sign')) {
$auth_template_path = jio_locate_template_file('templates/pages/page-sign.php');
return $auth_template_path ?: '';
}
@@ -243,13 +243,13 @@ function aksrt_get_current_special_template_path(): string {
$page_id = get_queried_object_id();
if ($page_id > 0) {
$page_template = get_post_meta($page_id, '_wp_page_template', true);
$resolved_template = aksrt_resolve_page_template_file(
$resolved_template = jio_resolve_page_template_file(
is_string($page_template) ? $page_template : '',
(string) get_post_field('post_name', $page_id)
);
if ($resolved_template !== '') {
$resolved_path = aksrt_locate_template_file($resolved_template);
$resolved_path = jio_locate_template_file($resolved_template);
if ($resolved_path) {
return $resolved_path;
}
@@ -265,8 +265,8 @@ function aksrt_get_current_special_template_path(): string {
*
* 用于前台直接访问固定 slug 时的自动补页。
*/
function aksrt_get_requested_template_key(): string {
global $_aksrt_special_templates;
function jio_get_requested_template_key(): string {
global $_jio_special_templates;
$request_uri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : '';
if ($request_uri === '') {
@@ -288,7 +288,7 @@ function aksrt_get_requested_template_key(): string {
return '';
}
foreach ($_aksrt_special_templates as $key => $cfg) {
foreach ($_jio_special_templates as $key => $cfg) {
$slug = isset($cfg['slug']) ? sanitize_title((string) $cfg['slug']) : '';
if ($slug !== '' && $slug === $request_slug) {
return (string) $key;
@@ -303,23 +303,23 @@ function aksrt_get_requested_template_key(): string {
*
* @param string $key 注册表 key
*/
function aksrt_ensure_template_page(string $key): void {
global $_aksrt_special_templates;
if (!isset($_aksrt_special_templates[$key])) return;
function jio_ensure_template_page(string $key): void {
global $_jio_special_templates;
if (!isset($_jio_special_templates[$key])) return;
$cfg = $_aksrt_special_templates[$key];
$cfg = $_jio_special_templates[$key];
if (array_key_exists('auto_create', $cfg) && empty($cfg['auto_create'])) {
return;
}
$desired_slug = sanitize_title($cfg['slug'] ?? $key);
// 已有页面使用此模板?仍校验模板 meta,避免空白默认页。
$found_page = aksrt_find_template_page($cfg['file']);
$found_page = jio_find_template_page($cfg['file']);
if ($found_page instanceof WP_Post) {
$current_tpl = get_post_meta((int) $found_page->ID, '_wp_page_template', true);
if ($current_tpl !== $cfg['file']) {
update_post_meta((int) $found_page->ID, '_wp_page_template', $cfg['file']);
aksrt_clear_template_page_cache();
jio_clear_template_page_cache();
}
return;
}
@@ -346,8 +346,8 @@ function aksrt_ensure_template_page(string $key): void {
if (!is_wp_error($page_id) && $page_id > 0) {
update_post_meta($page_id, '_wp_page_template', $cfg['file']);
update_post_meta($page_id, '_aksrt_managed_template_page', (string) $key);
aksrt_clear_template_page_cache();
update_post_meta($page_id, '_jio_managed_template_page', (string) $key);
jio_clear_template_page_cache();
}
}
+53 -53
View File
@@ -2,7 +2,7 @@
/**
* User public URL/page API
*
* @package AKSRT
* @package Jio
*/
defined('ABSPATH') || exit;
@@ -11,41 +11,41 @@ defined('ABSPATH') || exit;
// 五、公开 API 函数(兼容旧代码调用)
// ============================================================
if (!function_exists('aksrt_get_user_center_url')) :
if (!function_exists('jio_get_user_center_url')) :
/**
* 获取本人中心 URL(私有空间入口)
*
* @param string $tab 可选 tab 参数
* @return string
*/
function aksrt_get_user_center_url(string $tab = ''): string {
function jio_get_user_center_url(string $tab = ''): string {
$tab = sanitize_key($tab ?: 'vip');
$aliases = ['assets' => 'credits', 'signin' => 'credits', 'revenue' => 'revenue'];
$tab = $aliases[$tab] ?? $tab;
$path_tab = $tab === 'credits' ? 'balance' : $tab;
return get_option('permalink_structure')
? home_url('/user/' . trailingslashit($path_tab))
: add_query_arg(['aksrt_user_center' => '1', 'aksrt_user_center_tab' => $tab], home_url('/'));
: add_query_arg(['jio_user_center' => '1', 'jio_user_center_tab' => $tab], home_url('/'));
}
endif;
if (!function_exists('aksrt_get_new_post_url')) :
if (!function_exists('jio_get_new_post_url')) :
/**
* 前台写文章/投稿页 URL(模板 templates/pages/page-submit.php)。
*
* @param int $edit_id 编辑中的文章 ID;0 表示新建。
* @return string 未指派页面时返回空串。
*/
function aksrt_get_new_post_url(int $edit_id = 0): string {
if (class_exists('\AKSRT\Settings\Settings')) {
$submit = \AKSRT\Settings\Settings::get_submit_settings();
function jio_get_new_post_url(int $edit_id = 0): string {
if (class_exists('\Jio\Settings\Settings')) {
$submit = \Jio\Settings\Settings::get_submit_settings();
if (isset($submit['enabled']) && empty($submit['enabled'])) {
return '';
}
}
$url = function_exists('aksrt_get_template_url')
? aksrt_get_template_url('submit')
$url = function_exists('jio_get_template_url')
? jio_get_template_url('submit')
: home_url('/submit/');
if ($edit_id > 0) {
$url = add_query_arg('edit', $edit_id, $url);
@@ -54,21 +54,21 @@ function aksrt_get_new_post_url(int $edit_id = 0): string {
}
endif;
if (!function_exists('aksrt_get_messages_rewrite_slug')) :
if (!function_exists('jio_get_messages_rewrite_slug')) :
/** 获取消息中心当前唯一的重写别名。 */
function aksrt_get_messages_rewrite_slug(): string {
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::notification_settings()
function jio_get_messages_rewrite_slug(): string {
$settings = class_exists('\Jio\Settings\Settings')
? \Jio\Settings\Settings::notification_settings()
: [];
$slug = sanitize_key((string) ($settings['slug'] ?? 'messages'));
return $slug !== '' ? $slug : 'messages';
}
endif;
if (!function_exists('aksrt_get_messages_page_url')) :
if (!function_exists('jio_get_messages_page_url')) :
/** 消息中心 URL。 */
function aksrt_get_messages_page_url(string $view = 'unread'): string {
if (class_exists('\AKSRT\Settings\Settings') && !\AKSRT\Settings\Settings::message_enabled()) {
function jio_get_messages_page_url(string $view = 'unread'): string {
if (class_exists('\Jio\Settings\Settings') && !\Jio\Settings\Settings::message_enabled()) {
return '';
}
$suffixes = [
@@ -79,21 +79,21 @@ function aksrt_get_messages_page_url(string $view = 'unread'): string {
];
$view = sanitize_key($view);
$suffix = $suffixes[$view] ?? $suffixes['unread'];
$path = '/' . aksrt_get_messages_rewrite_slug() . ($suffix !== '' ? '/' . $suffix : '') . '/';
$path = '/' . jio_get_messages_rewrite_slug() . ($suffix !== '' ? '/' . $suffix : '') . '/';
return home_url($path);
}
endif;
if (!function_exists('aksrt_get_user_home_url')) :
if (!function_exists('jio_get_user_home_url')) :
/**
* 获取公开用户主页 URL(/user/{nicename}/)
*
* @param WP_User|int|string|null $user 用户对象、ID、nicename 或 null(当前用户)
* @return string
*/
function aksrt_get_user_home_url($user = null): string {
function jio_get_user_home_url($user = null): string {
$target = null;
$mode = class_exists('\\AKSRT\\Settings\\Settings') ? (string) (\AKSRT\Settings\Settings::get_user_home_settings()['route_identifier'] ?? 'nicename') : 'nicename';
$mode = class_exists('\\Jio\\Settings\\Settings') ? (string) (\Jio\Settings\Settings::get_user_home_settings()['route_identifier'] ?? 'nicename') : 'nicename';
if ($user instanceof WP_User) {
$target = $user;
} elseif (is_int($user) && $user > 0) {
@@ -110,15 +110,15 @@ function aksrt_get_user_home_url($user = null): string {
}
$identifier = $mode === 'uid' ? (string) $target->ID : $target->user_nicename;
if (!get_option('permalink_structure')) {
return add_query_arg('aksrt_author', rawurlencode($identifier), home_url('/'));
return add_query_arg('jio_author', rawurlencode($identifier), home_url('/'));
}
return home_url('/author/' . trailingslashit($identifier));
}
endif;
if (!function_exists('aksrt_resolve_public_user')) :
function aksrt_resolve_public_user(string $identifier): ?WP_User {
$mode = class_exists('\\AKSRT\\Settings\\Settings') ? (string) (\AKSRT\Settings\Settings::get_user_home_settings()['route_identifier'] ?? 'nicename') : 'nicename';
if (!function_exists('jio_resolve_public_user')) :
function jio_resolve_public_user(string $identifier): ?WP_User {
$mode = class_exists('\\Jio\\Settings\\Settings') ? (string) (\Jio\Settings\Settings::get_user_home_settings()['route_identifier'] ?? 'nicename') : 'nicename';
if ($mode === 'uid') {
return ctype_digit($identifier) && (int) $identifier > 0 ? get_userdata((int) $identifier) ?: null : null;
}
@@ -126,35 +126,35 @@ function aksrt_resolve_public_user(string $identifier): ?WP_User {
}
endif;
if (!function_exists('aksrt_is_user_center_page')) :
if (!function_exists('jio_is_user_center_page')) :
/**
* 判断当前是否为本人中心页面
*/
function aksrt_is_user_center_page(): bool {
return (bool) get_query_var('aksrt_user_center')
|| (is_page_template('templates/pages/page-profile.php') && !(bool) get_query_var('aksrt_author_identifier'));
function jio_is_user_center_page(): bool {
return (bool) get_query_var('jio_user_center')
|| (is_page_template('templates/pages/page-profile.php') && !(bool) get_query_var('jio_author_identifier'));
}
endif;
if (!function_exists('aksrt_is_user_home_page')) :
if (!function_exists('jio_is_user_home_page')) :
/**
* 判断当前是否为公开用户主页
*/
function aksrt_is_user_home_page(): bool {
return (bool) get_query_var('aksrt_author_identifier')
function jio_is_user_home_page(): bool {
return (bool) get_query_var('jio_author_identifier')
|| is_page_template('templates/pages/page-user-home.php');
}
endif;
if (!function_exists('aksrt_get_sign_page_url')) :
if (!function_exists('jio_get_sign_page_url')) :
/**
* Get the only public authentication page URL.
*
* @param string $tab
* @param array<string, scalar> $args
*/
function aksrt_get_sign_page_url(string $tab = 'signin', array $args = []): string {
$tab = aksrt_normalize_auth_tab($tab);
function jio_get_sign_page_url(string $tab = 'signin', array $args = []): string {
$tab = jio_normalize_auth_tab($tab);
return add_query_arg(['tab' => $tab] + $args, home_url('/sign/'));
}
@@ -162,16 +162,16 @@ function aksrt_get_sign_page_url(string $tab = 'signin', array $args = []): stri
/**
* Determine whether the current request is served by the unified auth experience.
*/
function aksrt_is_auth_page_request(): bool {
return (bool) get_query_var('aksrt_sign')
function jio_is_auth_page_request(): bool {
return (bool) get_query_var('jio_sign')
|| is_page_template('templates/pages/page-sign.php');
}
endif;
if (!function_exists('aksrt_get_login_url')) :
if (!function_exists('jio_get_login_url')) :
/** 获取登录页 URL */
function aksrt_get_login_url($redirect = '') {
$url = aksrt_get_sign_page_url('signin');
function jio_get_login_url($redirect = '') {
$url = jio_get_sign_page_url('signin');
if ($redirect) {
$url = add_query_arg('redirect_to', urlencode($redirect), $url);
}
@@ -179,17 +179,17 @@ function aksrt_get_login_url($redirect = '') {
}
endif;
if (!function_exists('aksrt_get_register_url')) :
if (!function_exists('jio_get_register_url')) :
/** 获取注册页 URL */
function aksrt_get_register_url() {
return aksrt_get_sign_page_url('signup');
function jio_get_register_url() {
return jio_get_sign_page_url('signup');
}
endif;
if (!function_exists('aksrt_get_bind_url')) :
if (!function_exists('jio_get_bind_url')) :
/** 获取绑定账号页面 URL */
function aksrt_get_bind_url($transient_key = '') {
$url = aksrt_get_sign_page_url('bind');
function jio_get_bind_url($transient_key = '') {
$url = jio_get_sign_page_url('bind');
if ($transient_key) {
$url = add_query_arg('obk', $transient_key, $url);
}
@@ -197,31 +197,31 @@ function aksrt_get_bind_url($transient_key = '') {
}
endif;
if (!function_exists('aksrt_get_logout_url')) :
if (!function_exists('jio_get_logout_url')) :
/** 获取唯一退出登录 URL。 */
function aksrt_get_logout_url($redirect = '') {
function jio_get_logout_url($redirect = '') {
$target = is_string($redirect) && $redirect !== '' ? $redirect : home_url('/');
$url = add_query_arg(
['redirect_to' => $target],
home_url('/logout/')
);
return wp_nonce_url($url, 'aksrt-logout');
return wp_nonce_url($url, 'jio-logout');
}
endif;
if (!function_exists('aksrt_get_reset_password_url')) :
if (!function_exists('jio_get_reset_password_url')) :
/**
* 获取重置密码页面 URL
*
* @return string
*/
function aksrt_get_reset_password_url(): string {
return aksrt_get_sign_page_url('resetpassword');
function jio_get_reset_password_url(): string {
return jio_get_sign_page_url('resetpassword');
}
endif;
// Notifications live in the same user/ domain; bootstrap also loads it.
if (!class_exists('AKSRT_User_Notifications', false) /* procedural module */ && file_exists(dirname(__DIR__) . '/user-notifications.php')) {
if (!class_exists('JIO_User_Notifications', false) /* procedural module */ && file_exists(dirname(__DIR__) . '/user-notifications.php')) {
require_once dirname(__DIR__) . '/user-notifications.php';
}