Files
wordpress-theme-aksrt/inc/core-hooks/part-3.php
T
kate522 5fd7c212ed fix(runtime): 按参考主题硬切换为 loader/main/auto_fun 单一 DOM 生命周期
- 删除 AksrtFrontend registry/rehydrate 双路架构及 build/public.js 拼包入口,
  前台唯一初始路径为 PHP 本地栈(jQuery 1.9.1 → Bootstrap 3.4.1)
  → loader_js(_win/aksrtData 唯一注入)→ tbquire(['main']) → runtime/main.min.js
- window.auto_fun = debounce(z_auto_fun, 100) 为唯一重扫入口;所有模块改为
  执行一次 + off/on('auto_fun.aksrt-*') 命名空间重扫,data/class 标记幂等
- 局部更新协议统一:HTML 注入 → post_ajax.ed → auto_fun();
  远程 modal → loaded.bs.modal → auto_fun();JSON 成功 → zib_ajax.success
- 灯箱恢复 Miniimgbox/imgbox 唯一 owner(imgbox-container、a[data-imgbox]、
  imgbox_data),删除 AksrtLightbox/data-aksrt-lightbox 第二实现及 CSS/overlay,
  _win.imgbox* 重新接上 post-display 设置
- 死代码清理:runtime 下 11 组被自有实现替代的旧模块副本、无消费 vendored 库、
  顶层 grade.min.js、revenue.js、无调用方的 aksrt_get_win_runtime_config(),
  以及 loader 中 16 条死 mapping
- PHP 入队改为本地栈 + loader_js,routed/widget/submit 依赖统一换绑;
  用户卡片发布按钮恢复 nav_user_newposts_btn 设置门控
- 测试对齐:新增 frontend-lifecycle-contract,重写 navigation/lazyload/toast/
  auth-source/comment/page-display/post-visual 等断言为目标架构契约

验证:node --test widget-system+navigation 223 通过 0 失败;
构建脚本重建 main/imgbox min 与 CSS bundles;改动 PHP php -l、JS node --check
全部通过;git diff --check 干净;credits 重入 harness 通过。
2026-09-03 12:44:31 +08:00

253 lines
9.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
defined('ABSPATH') || exit;
// EnlighterJS 代码高亮 — 白名单 data-enlighter-* 属性
// ============================================================
add_filter('wp_kses_allowed_html', function ($allowed, $context) {
if ($context !== 'post') {
return $allowed;
}
// Allow data-enlighter-* attributes on <pre> and <code>
$enlighter_attrs = [
'data-enlighter-language' => true,
'data-enlighter-theme' => true,
'data-enlighter-group' => true,
'data-enlighter-title' => true,
'data-enlighter-linenumbers' => true,
'data-enlighter-highlight' => true,
'data-enlighter-lineoffset' => true,
];
if (isset($allowed['pre'])) {
$allowed['pre'] = array_merge($allowed['pre'], $enlighter_attrs);
}
if (isset($allowed['code'])) {
$allowed['code'] = array_merge($allowed['code'], $enlighter_attrs);
}
return $allowed;
}, 10, 2);
// ============================================================
// WP 后台文章列表增强列 — 浏览/点赞/收藏/下载
// ============================================================
add_filter('manage_post_posts_columns', function ($columns) {
$new_columns = [];
foreach ($columns as $key => $label) {
$new_columns[$key] = $label;
if ($key === 'title') {
$new_columns['aksrt_stats'] = __('互动数据', 'aksrt');
}
}
return $new_columns;
});
add_action('admin_enqueue_scripts', function ($hook) {
if ($hook !== 'edit.php') return;
wp_enqueue_style(
'aksrt-font-awesome',
get_template_directory_uri() . '/assets/fontawesome5/css/all.min.css',
[],
'5.15.4'
);
});
add_action('manage_post_posts_custom_column', function ($column, $post_id) {
if ($column !== 'aksrt_stats') return;
$views = (int) get_post_meta($post_id, 'views', true);
$likes = (int) get_post_meta($post_id, 'like', true);
$favorites = (int) get_post_meta($post_id, 'favorite', true);
$downloads = (int) get_post_meta($post_id, 'download_count', true);
$format = function (int $n): string {
if ($n >= 10000) return round($n / 10000, 1) . '万';
if ($n >= 1000) return round($n / 1000, 1) . 'k';
return (string) $n;
};
$parts = [];
$parts[] = '<span title="' . esc_attr__('浏览', 'aksrt') . '" style="margin-right:4px;"><i class="fa fas fa-eye" style="color:#8a909c;font-size:12px;"></i> ' . esc_html($format($views)) . '</span>';
$parts[] = '<span title="' . esc_attr__('点赞', 'aksrt') . '" style="margin-right:4px;"><i class="fa fas fa-thumbs-up" style="color:#1890ff;font-size:12px;"></i> ' . esc_html($format($likes)) . '</span>';
$parts[] = '<span title="' . esc_attr__('收藏', 'aksrt') . '" style="margin-right:4px;"><i class="fa fas fa-star" style="color:#f39c12;font-size:12px;"></i> ' . esc_html($format($favorites)) . '</span>';
if ($downloads > 0) {
$parts[] = '<span title="' . esc_attr__('下载', 'aksrt') . '"><i class="fa fas fa-download" style="color:#52c41a;font-size:12px;"></i> ' . esc_html($format($downloads)) . '</span>';
}
echo implode(' &middot; ', $parts);
}, 10, 2);
// Support sorting by views/likes/favorites in admin
add_action('pre_get_posts', function ($query) {
if (!is_admin() || !$query->is_main_query()) return;
$orderby = $query->get('orderby');
$allowed = ['views', 'like', 'favorite', 'download_count'];
if (in_array($orderby, $allowed, true)) {
$query->set('meta_key', $orderby);
$query->set('orderby', 'meta_value_num');
}
});
// ============================================================
// 评论提交:单一合同
// ------------------------------------------------------------
// 主路径:前端 comments.js → REST /comment/submit(aksrt_require_captcha)。
// 兜底 / 原生 wp-comments-post.php 经 preprocess_comment 做人机验证,避免绕过。
// 列表仍由 aksrt_comment_callback 统一渲染。
// ============================================================
// ============================================================
// Gutenberg 自定义块注册
// ============================================================
// Register category server-side so it exists before JS registerBlockType runs.
// Keep untyped + defensive: some plugins pass unexpected shapes; typed params can 500 the editor.
add_filter('block_categories_all', static function ($categories, $context = null) {
if (!is_array($categories)) {
return $categories;
}
foreach ($categories as $category) {
$slug = '';
if (is_array($category)) {
$slug = (string) ($category['slug'] ?? '');
} elseif (is_object($category) && isset($category->slug)) {
$slug = (string) $category->slug;
}
if ($slug === 'aksrt-blocks') {
return $categories;
}
}
$categories[] = [
'slug' => 'aksrt-blocks',
'title' => 'AKSRT',
'icon' => null,
];
return $categories;
}, 10, 2);
add_action('enqueue_block_editor_assets', function () {
$base_uri = get_template_directory_uri();
$version = wp_get_theme()->get('Version');
$blocks_js = get_template_directory() . '/assets/js/gutenberg-blocks.js';
if (file_exists($blocks_js)) {
wp_enqueue_script(
'aksrt-gutenberg-blocks',
$base_uri . '/assets/js/gutenberg-blocks.js',
// wp-media-utils: MediaUpload for carousel block
['wp-blocks', 'wp-element', 'wp-components', 'wp-block-editor', 'wp-hooks', 'wp-media-utils', 'wp-data'],
(string) filemtime($blocks_js),
true
);
}
$blocks_css = get_template_directory() . '/assets/css/gutenberg-blocks.css';
if (file_exists($blocks_css)) {
wp_enqueue_style(
'aksrt-gutenberg-blocks',
$base_uri . '/assets/css/gutenberg-blocks.css',
[],
(string) filemtime($blocks_css)
);
}
});
// Front-end styles for Gutenberg blocks
add_action('enqueue_block_assets', function () {
if (is_admin()) return; // Already loaded in editor
$posts = [];
$queried = get_queried_object();
if ($queried instanceof \WP_Post) {
$posts[$queried->ID] = $queried;
}
global $wp_query;
if ($wp_query instanceof \WP_Query) {
foreach ((array) $wp_query->posts as $post) {
if ($post instanceof \WP_Post) {
$posts[$post->ID] = $post;
}
}
}
$has_carousel = false;
foreach ($posts as $post) {
if (has_block('aksrt/carousel', $post)) {
$has_carousel = true;
break;
}
}
if (!$has_carousel) return;
$base_uri = get_template_directory_uri();
$blocks_css = get_template_directory() . '/assets/css/gutenberg-blocks.css';
if (file_exists($blocks_css)) {
wp_enqueue_style(
'aksrt-gutenberg-blocks-front',
$base_uri . '/assets/css/gutenberg-blocks.css',
[],
(string) filemtime($blocks_css)
);
}
});
// ============================================================
// Gutenberg Carousel Block 渲染回调
// ============================================================
add_action('init', function () {
if (!function_exists('register_block_type')) return;
register_block_type('aksrt/carousel', [
'render_callback' => function (array $attributes): string {
$images = $attributes['images'] ?? [];
if (empty($images)) return '';
$autoplay = !empty($attributes['autoplay']) ? 'true' : 'false';
$delay = absint($attributes['delay'] ?? 3000);
$effect = sanitize_text_field($attributes['effect'] ?? 'slide');
$slides = '';
foreach ($images as $img) {
if (empty($img['url'])) continue;
$alt = esc_attr($img['alt'] ?? '');
$url = esc_url($img['url']);
$slides .= '<div class="swiper-slide"><img' . aksrt_get_lazy_attr('lazy_sider', (string) $url, '', aksrt_get_lazy_thumb('lg')) . ' alt="' . $alt . '"></div>';
}
if (empty($slides)) return '';
return '<div class="aksrt-carousel-block swiper" data-autoplay="' . $autoplay . '" data-delay="' . $delay . '" data-effect="' . $effect . '">'
. '<div class="swiper-wrapper">' . $slides . '</div>'
. '<div class="swiper-pagination"></div>'
. '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>'
. '</div>';
},
]);
});
// ============================================================
// 付费内容系统:the_content 过滤器
// ============================================================
/**
* 未购买的图库/视频正文只保留公开预览;购买卡由 single 模板渲染。
*/
add_filter('the_content', 'aksrt_paid_content_filter', 20);
/**
* 付费/资源文章使用统一的 single.php。
*/
add_filter('single_template', function (string $template): string {
return $template;
});