refactor(classes): organize inc/classes into domain folders

Move ~94 root class shells and root *-traits into domain directories
(core, auth, user, credits, content, payment/gateways, forum, shop,
sms, ai, messages, extensions, widgets, settings, admin). Update
bootstrap require paths, co-locate traits with owners, fix forum/user
relative requires, drop duplicate shop controller requires, and wire
home-modules load. Path-only; class names and init order unchanged.
This commit is contained in:
kate522 committed 2026-07-17 11:11:57 +08:00
1 parent 2a8fe68048
commit ce1c13b947
115 files changed
+171 -224

No files matched your search

@@ -0,0 +1,518 @@
<?php
/**
* AKSRT 自定义小工具
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
// ============================================================
// 1. 用户中心小工具 — 替换旧作者信息小工具
// ============================================================
class AKSRT_About_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'aksrt_about',
esc_html__('AKSRT 用户中心', 'aksrt'),
[
'description' => esc_html__('登录状态面板:未登录显示登录/注册按钮,已登录显示用户信息与快捷入口', 'aksrt'),
'customize_selective_refresh' => true,
]
);
}
/**
* 前端渲染
*/
public function widget($args, $instance): void {
echo $args['before_widget'];
$title = apply_filters('widget_title', $instance['title'] ?? '', $instance, $this->id_base);
if ($title) {
echo $args['before_title'] . esc_html($title) . $args['after_title'];
}
// 判断登录状态
if (is_user_logged_in()) {
$this->render_logged_in();
} else {
$this->render_logged_out($instance);
}
// 输出内联样式 & JS(仅在本 widget 实例加载时注入一次)
$this->inline_assets();
echo $args['after_widget'];
}
// ==========================================
// 已登录状态渲染(Zibll 风格用户卡片)
// ==========================================
private function render_logged_in(): void {
$u = wp_get_current_user();
$avatar = get_avatar_url($u->ID, ['size' => 160]);
$profile = aksrt_get_user_center_url();
$logout = aksrt_get_logout_url(home_url('/'));
// 封面图:用户在用户中心上传的背景图 > 默认背景图
$cover = get_user_meta($u->ID, 'aksrt_background_image', true);
if (! $cover) {
$cover = get_theme_file_uri('assets/img/person_background.png');
}
?>
<div class="aksrt-user-card">
<div class="aksrt-user-card__cover" style="padding-bottom: 50%;">
<img class="aksrt-user-card__cover-img" src="<?php echo esc_url($cover); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('widget') : ' loading="lazy"'; ?>>
</div>
<div class="aksrt-user-card__content">
<div class="aksrt-user-card__avatar">
<img src="<?php echo esc_url($avatar); ?>" alt="" width="80" height="80"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('avatar') : ' loading="lazy"'; ?>>
</div>
<div class="aksrt-user-card__info">
<div class="aksrt-user-card__name"><?php echo esc_html($u->display_name); ?></div>
<div class="aksrt-user-card__desc"><?php echo esc_html($u->user_email); ?></div>
</div>
<div class="aksrt-user-card__btns">
<a class="aksrt-user-card__btn aksrt-user-card__btn--primary" href="<?php echo esc_url($profile); ?>">
<i class="fas fa-user" aria-hidden="true"></i> <?php esc_html_e('个人主页', 'aksrt'); ?>
</a>
<a class="aksrt-user-card__btn aksrt-user-card__btn--outline" href="<?php echo esc_url($logout); ?>">
<i class="fas fa-sign-out-alt" aria-hidden="true"></i> <?php esc_html_e('退出', 'aksrt'); ?>
</a>
</div>
</div>
</div>
<?php
}
// ==========================================
// 未登录状态渲染(Zibll 风格用户卡片)
// ==========================================
private function render_logged_out(array $instance = []): void {
$login_url = aksrt_get_login_url();
$register_url = aksrt_get_register_url();
// 封面图:后台配置 > 默认
$cover = ! empty($instance['cover']) ? $instance['cover'] : get_theme_file_uri('assets/img/widgets-original.png');
$avatar = get_avatar_url(0, ['size' => 160, 'default' => 'mystery']);
$oauth_html = '';
if (function_exists('AKSRT_OAuth') && method_exists(AKSRT_OAuth::get_instance(), 'get_login_buttons')) {
$oauth_html = AKSRT_OAuth::get_instance()->get_login_buttons();
}
?>
<div class="aksrt-user-card">
<div class="aksrt-user-card__cover" style="padding-bottom: 50%;">
<?php if ($cover) : ?>
<img class="aksrt-user-card__cover-img" src="<?php echo esc_url($cover); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('widget') : ' loading="lazy"'; ?>>
<?php endif; ?>
</div>
<div class="aksrt-user-card__content">
<div class="aksrt-user-card__avatar">
<img src="<?php echo esc_url($avatar); ?>" alt="" width="80" height="80"<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('avatar') : ' loading="lazy"'; ?>>
</div>
<div class="aksrt-user-card__info">
<div class="aksrt-user-card__desc"><?php esc_html_e('Hi! 请登录', 'aksrt'); ?></div>
</div>
<div class="aksrt-user-card__btns">
<a class="aksrt-user-card__btn aksrt-user-card__btn--primary" href="<?php echo esc_url($login_url); ?>"><?php esc_html_e('登 录', 'aksrt'); ?></a>
<?php if (get_option('users_can_register')) : ?>
<a class="aksrt-user-card__btn aksrt-user-card__btn--outline" href="<?php echo esc_url($register_url); ?>"><?php esc_html_e('注 册', 'aksrt'); ?></a>
<?php endif; ?>
</div>
<?php if ($oauth_html) : ?>
<div class="aksrt-user-card__oauth">
<div class="aksrt-user-card__divider"><?php esc_html_e('社交账号登录', 'aksrt'); ?></div>
<div class="aksrt-user-card__social-icons">
<?php echo $oauth_html; ?>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php
}
// ==========================================
// 内联样式(Zibll 风格用户卡片,只输出一次)
// ==========================================
private function inline_assets(): void {
if (did_action('aksrt_user_card_assets')) {
return;
}
do_action('aksrt_user_card_assets');
?>
<style>
/* ========== AKSRT 用户卡片(Zibll 风格) ========== */
/*
* 消除"卡片套卡片":
* 外层 .widget-card 提供 background/shadow/border-radius/padding:15px
* 内层 .aksrt-user-card 用负 margin 把封面图扩展到外层边缘,
* 使封面图与外层卡片融为一体,不再有 15px 间距。
*/
.widget-card > .aksrt-user-card {
margin: -15px -15px 0;
overflow: hidden;
border-radius: var(--radius-card, 8px) var(--radius-card, 8px) 0 0;
}
/* 有标题时:取消标题下方的 margin-bottom,因为卡片已无额外间距 */
.widget.aksrt_about.widget-card > .widget-title + .aksrt-user-card {
margin-top: -5px;
}
/* ---- 封面图 ---- */
.aksrt-user-card__cover {
position: relative;
overflow: hidden;
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark, #4f46e5));
}
.aksrt-user-card__cover-img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
/* ---- 内容区 — 悬浮在封面上方 ---- */
.aksrt-user-card__content {
padding: 15px;
margin-top: -55px;
position: relative;
text-align: center;
}
/* ---- 头像(绝对居中) ---- */
.aksrt-user-card__avatar {
text-align: center;
line-height: 0;
}
.aksrt-user-card__avatar img {
display: block;
width: 80px;
height: 80px;
margin: 0 auto;
border-radius: 50%;
border: 3px solid var(--color-primary);
object-fit: cover;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
/* ---- 用户信息 ---- */
.aksrt-user-card__info {
margin-top: 12px;
text-align: center;
}
.aksrt-user-card__name {
font-size: 1.1em;
font-weight: bold;
color: var(--color-ink, var(--color-text));
}
.aksrt-user-card__desc {
font-size: 13px;
color: var(--color-text-muted, #9ca3af);
margin-top: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ---- 按钮组 ---- */
.aksrt-user-card__btns {
display: flex;
gap: 10px;
justify-content: center;
margin-top: 16px;
}
.aksrt-user-card__btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px 20px;
border-radius: 20px;
font-size: 13px;
font-weight: 600;
text-decoration: none;
transition: opacity 0.2s ease, transform 0.15s ease;
flex: 1;
max-width: 140px;
}
.aksrt-user-card__btn:hover {
opacity: 0.88;
transform: translateY(-1px);
}
.aksrt-user-card__btn:active {
transform: translateY(0);
}
.aksrt-user-card__btn--primary {
background: var(--color-primary);
color: #fff;
}
.aksrt-user-card__btn--outline {
background: var(--color-primary-softer, rgba(136,171,218,0.05));
color: var(--color-primary);
border: 1px solid var(--color-primary-50, rgba(136,171,218,0.12));
}
/* ---- OAuth 社交登录 ---- */
.aksrt-user-card__oauth {
margin-top: 12px;
}
.aksrt-user-card__divider {
font-size: 12px;
color: var(--color-text-muted, #9ca3af);
margin-bottom: 10px;
position: relative;
}
.aksrt-user-card__divider::before,
.aksrt-user-card__divider::after {
content: '';
position: absolute;
top: 50%;
width: 28%;
height: 1px;
background: var(--color-border, #e5e7eb);
}
.aksrt-user-card__divider::before { left: 0; }
.aksrt-user-card__divider::after { right: 0; }
.aksrt-user-card__social-icons {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
}
.aksrt-user-card__social-icons a {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
border-radius: 50%;
font-size: 15px;
color: var(--color-text-muted, #6b7280);
background: var(--color-bg-tertiary, #f3f4f6);
text-decoration: none;
transition: background 0.18s ease, color 0.18s ease;
}
.aksrt-user-card__social-icons a:hover {
background: var(--color-primary);
color: #fff;
}
/* ---- 暗色适配 ---- */
html.dark .aksrt-user-card__avatar img,
body.theme-dark .aksrt-user-card__avatar img {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
html.dark .aksrt-user-card__social-icons a,
body.theme-dark .aksrt-user-card__social-icons a {
background: rgba(255, 255, 255, 0.08);
}
html.dark .aksrt-user-card__social-icons a:hover,
body.theme-dark .aksrt-user-card__social-icons a:hover {
background: var(--color-primary);
}
/* ---- 移动端 ---- */
@media screen and (max-width: 480px) {
.aksrt-user-card__content {
margin-top: -45px;
}
.aksrt-user-card__avatar img {
width: 68px;
height: 68px;
}
}
</style>
<?php
}
// ==========================================
// 后台表单
// ==========================================
public function form($instance): void {
$title = $instance['title'] ?? '';
$cover = $instance['cover'] ?? '';
$default_cover = get_theme_file_uri('assets/img/widgets-original.png');
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php esc_html_e('标题(可选):', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
name="<?php echo $this->get_field_name('title'); ?>"
type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id('cover'); ?>"><?php esc_html_e('未登录背景图 URL:', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('cover'); ?>"
name="<?php echo $this->get_field_name('cover'); ?>"
type="url" value="<?php echo esc_attr($cover); ?>"
placeholder="<?php echo esc_attr($default_cover); ?>">
</p>
<p style="font-size:12px;color:#666;">
<?php esc_html_e('留空则使用默认背景图。已登录用户可使用个人封面图。', 'aksrt'); ?>
</p>
<?php
}
public function update($new_instance, $old_instance): array {
return [
'title' => sanitize_text_field($new_instance['title'] ?? ''),
'cover' => esc_url_raw($new_instance['cover'] ?? ''),
];
}
}
// ============================================================
// 2. 分类目录小工具
// ============================================================
class AKSRT_Categories_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'aksrt_categories',
esc_html__('AKSRT 分类目录', 'aksrt'),
array(
'description' => esc_html__('以列表形式展示文章分类', 'aksrt'),
'customize_selective_refresh' => true,
)
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
$title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
if ($title): ?>
<h3 class="widget-title"><?php echo $title; ?></h3>
<?php endif;
$count = absint($instance['count'] ?: 8);
$cats = get_categories(array('number' => $count, 'orderby' => 'count', 'order' => 'DESC'));
?>
<ul class="widget-list">
<?php foreach ($cats as $cat): ?>
<li>
<a href="<?php echo esc_url(get_category_link($cat->term_id)); ?>"><?php echo esc_html($cat->name); ?></a>
<span><?php echo (int)$cat->count; ?></span>
</li>
<?php endforeach; ?>
</ul>
<?php
echo $args['after_widget'];
}
public function form($instance) {
$title = $instance['title'] ?? __('分类目录', 'aksrt');
$count = isset($instance['count']) ? (int)$instance['count'] : 8;
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
name="<?php echo $this->get_field_name('title'); ?>"
type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id('count'); ?>"><?php esc_html_e('显示数量:', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo $this->get_field_id('count'); ?>"
name="<?php echo $this->get_field_name('count'); ?>"
type="number" min="1" max="50" value="<?php echo $count; ?>">
</p>
<?php
}
public function update($new, $old) {
return [
'title' => sanitize_text_field($new['title']),
'count' => absint($new['count']),
];
}
}
// ============================================================
// 3. 标签云小工具
// ============================================================
class AKSRT_Tag_Cloud_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'aksrt_tag_cloud',
esc_html__('AKSRT 标签云', 'aksrt'),
array(
'description' => esc_html__('展示文章标签云', 'aksrt'),
'customize_selective_refresh' => true,
)
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
$title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
$count = absint($instance['count'] ?: 15);
if ($title): ?>
<h3 class="widget-title"><?php echo $title; ?></h3>
<?php endif;
?>
<div class="tag-cloud">
<?php
$tags = get_tags(['number' => $count, 'orderby' => 'count', 'order' => 'DESC']);
foreach ($tags as $tag):
$size = 12 + min(4, (int)($tag->count / 5));
?>
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" style="font-size:<?php echo $size ?>px;">#<?php echo esc_html($tag->name); ?></a>
<?php endforeach; ?>
</div>
<?php
echo $args['after_widget'];
}
public function form($instance) {
$title = $instance['title'] ?? __('标签云', 'aksrt');
$count = isset($instance['count']) ? (int)$instance['count'] : 15;
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
name="<?php echo $this->get_field_name('title'); ?>"
type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id('count'); ?>"><?php esc_html_e('标签数量:', 'aksrt'); ?></label>
<input class="tiny-text" id="<?php echo $this->get_field_id('count'); ?>"
name="<?php echo $this->get_field_name('count'); ?>"
type="number" min="1" max="50" value="<?php echo $count; ?>">
</p>
<?php
}
public function update($new, $old) {
return [
'title' => sanitize_text_field($new['title']),
'count' => absint($new['count']),
];
}
}
// 注册函数已迁移至 class-aksrt-widgets.php(注册中心)