refactor: flatten src/AKSRT → src (drop theme-identifier dir)
Move all domain folders from src/AKSRT/{Domain} to src/{Domain}; remap
Composer PSR-4 "AKSRT\\": "src/"; update audit script + README + ADR
paths; remove dead tools/build-psr4-map.php (scanned deleted inc/classes).
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
namespace AKSRT\Core;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class Setup {
|
||||
use SetupPart1;
|
||||
use SetupPart2;
|
||||
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function get_instance(): self {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function init(): void {
|
||||
add_action('after_setup_theme', [$this, 'load_textdomain'], 1);
|
||||
add_action('after_setup_theme', [$this, 'setup_theme']);
|
||||
add_action('widgets_init', [$this, 'register_sidebars']);
|
||||
add_filter('dynamic_sidebar_params', [$this, 'filter_sidebar_widget_params']);
|
||||
add_action('init', [$this, 'register_nav_menus'], 0);
|
||||
add_action('init', [$this, 'register_post_types'], 1);
|
||||
add_action('init', [$this, 'register_meta_fields'], 5);
|
||||
// 文章浏览量统计(单次访问)
|
||||
add_action('wp', 'aksrt_set_post_views');
|
||||
// 隐藏默认WordPress管理菜单
|
||||
add_action('admin_menu', [$this, 'hide_default_menus'], 999);
|
||||
}
|
||||
|
||||
public function load_textdomain(): void {
|
||||
load_theme_textdomain('aksrt', AKSRT_DIR . '/languages');
|
||||
}
|
||||
|
||||
public function setup_theme(): void {
|
||||
|
||||
// HTML5 支持
|
||||
add_theme_support('html5', [
|
||||
'search-form', 'comment-form', 'comment-list',
|
||||
'gallery', 'caption', 'style', 'script',
|
||||
'navigation-widgets',
|
||||
]);
|
||||
|
||||
add_theme_support('title-tag');
|
||||
add_theme_support('post-thumbnails');
|
||||
add_theme_support('custom-logo', [
|
||||
'height' => 120,
|
||||
'width' => 300,
|
||||
'flex-height' => true,
|
||||
'flex-width' => true,
|
||||
'header-text' => true,
|
||||
]);
|
||||
add_theme_support('customize-selective-refresh-widgets');
|
||||
add_theme_support('align-wide');
|
||||
add_theme_support('wp-block-styles');
|
||||
add_theme_support('responsive-embeds');
|
||||
|
||||
// 文章格式
|
||||
add_theme_support('post-formats', ['aside', 'image', 'video', 'quote', 'link', 'gallery']);
|
||||
|
||||
// 图片尺寸
|
||||
add_image_size('aksrt-cover', 1200, 675, true);
|
||||
add_image_size('aksrt-card', 400, 260, true);
|
||||
add_image_size('aksrt-thumb', 150, 150, true);
|
||||
add_image_size('aksrt-banner', 1920, 500, true);
|
||||
|
||||
// 内容宽度(用于区块编辑器)
|
||||
if (!isset($GLOBALS['content_width'])) {
|
||||
$GLOBALS['content_width'] = 900;
|
||||
}
|
||||
}
|
||||
|
||||
public function register_nav_menus(): void {
|
||||
register_nav_menus([
|
||||
'primary' => __('主导航', 'aksrt'),
|
||||
'mobile' => __('移动端菜单', 'aksrt'),
|
||||
'footer' => __('页脚菜单', 'aksrt'),
|
||||
'social' => __('社交链接', 'aksrt'),
|
||||
'header_actions' => __('顶部右侧入口', 'aksrt'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册自定义文章类型
|
||||
*
|
||||
* 资源不是 CPT:元数据挂在普通 post 上,
|
||||
* 通过 _aksrt_is_resource meta 标记是否为资源。
|
||||
*/
|
||||
public function register_post_types(): void {
|
||||
// 项目展示
|
||||
register_post_type('project', [
|
||||
'labels' => [
|
||||
'name' => __('项目展示', 'aksrt'),
|
||||
'singular_name' => __('项目', 'aksrt'),
|
||||
'add_new' => __('新建项目', 'aksrt'),
|
||||
'add_new_item' => __('新建项目', 'aksrt'),
|
||||
'edit_item' => __('编辑项目', 'aksrt'),
|
||||
'new_item' => __('新项目', 'aksrt'),
|
||||
'view_item' => __('查看项目', 'aksrt'),
|
||||
'search_items' => __('搜索项目', 'aksrt'),
|
||||
'not_found' => __('未找到项目', 'aksrt'),
|
||||
'not_found_in_trash' => __('回收站中无项目', 'aksrt'),
|
||||
'menu_name' => __('项目展示', 'aksrt'),
|
||||
],
|
||||
'public' => true,
|
||||
'publicly_queryable' => true,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'show_in_nav_menus' => false,
|
||||
'has_archive' => false,
|
||||
'hierarchical' => false,
|
||||
'menu_position' => 25,
|
||||
'menu_icon' => 'dashicons-portfolio',
|
||||
'supports' => ['title', 'editor', 'excerpt', 'thumbnail', 'author', 'revisions'],
|
||||
'rewrite' => ['slug' => 'project'],
|
||||
'capability_type' => 'post',
|
||||
'map_meta_cap' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册资源 post meta + 分类 term meta(aksrt_flow)
|
||||
*
|
||||
* 全部 show_in_rest,便于 Block Editor + Vue SPA 读写。
|
||||
*
|
||||
* v3.4: 资源元数据全部挂在 post 上,配合 _aksrt_is_resource 开关使用。
|
||||
*/
|
||||
public function register_meta_fields(): void {
|
||||
$post_edit_auth = static function () {
|
||||
return current_user_can('edit_posts');
|
||||
};
|
||||
|
||||
// Core switch: mark a post as resource.
|
||||
register_post_meta('post', DomainModel::RESOURCE_MARKER_KEY, [
|
||||
'type' => 'boolean',
|
||||
'description' => 'Whether this post is a resource post.',
|
||||
'single' => true,
|
||||
'default' => false,
|
||||
'show_in_rest' => true,
|
||||
'sanitize_callback' => static function ($v) { return (bool) $v; },
|
||||
'auth_callback' => $post_edit_auth,
|
||||
]);
|
||||
|
||||
register_post_meta('post', DomainModel::PAY_META_KEY, [
|
||||
'type' => 'object',
|
||||
'description' => 'Canonical paid content payload.',
|
||||
'single' => true,
|
||||
'default' => DomainModel::default_pay_meta(),
|
||||
'show_in_rest' => [
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'pay_type' => [
|
||||
'type' => 'string',
|
||||
'enum' => array_keys(DomainModel::pay_type_labels()),
|
||||
],
|
||||
'price' => ['type' => 'number'],
|
||||
'original_price' => ['type' => 'number'],
|
||||
'vip1_price' => ['type' => 'number'],
|
||||
'vip2_price' => ['type' => 'number'],
|
||||
'version' => ['type' => 'string'],
|
||||
'size' => ['type' => 'string'],
|
||||
'license' => ['type' => 'string'],
|
||||
'compat' => ['type' => 'string'],
|
||||
'demo_url' => ['type' => 'string', 'format' => 'uri'],
|
||||
'video_url' => ['type' => 'string', 'format' => 'uri'],
|
||||
'downloads' => [
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'label' => ['type' => 'string'],
|
||||
'url' => ['type' => 'string', 'format' => 'uri'],
|
||||
'type' => ['type' => 'string'],
|
||||
'extract_code' => ['type' => 'string'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'attributes' => [
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'key' => ['type' => 'string'],
|
||||
'value' => ['type' => 'string'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'gallery' => [
|
||||
'type' => 'array',
|
||||
'items' => ['type' => 'string', 'format' => 'uri'],
|
||||
],
|
||||
'require_login' => ['type' => 'boolean'],
|
||||
'require_captcha' => ['type' => 'boolean'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'sanitize_callback' => [DomainModel::class, 'sanitize_pay_meta'],
|
||||
'auth_callback' => $post_edit_auth,
|
||||
]);
|
||||
|
||||
register_post_meta('post', DomainModel::PAY_TYPE_KEY, [
|
||||
'type' => 'string',
|
||||
'description' => 'Query-friendly paid content type.',
|
||||
'single' => true,
|
||||
'default' => DomainModel::PAY_TYPE_NO,
|
||||
'show_in_rest' => true,
|
||||
'sanitize_callback' => [DomainModel::class, 'normalize_pay_type'],
|
||||
'auth_callback' => $post_edit_auth,
|
||||
]);
|
||||
|
||||
register_post_meta('post', DomainModel::PAY_PRICE_KEY, [
|
||||
'type' => 'number',
|
||||
'description' => 'Query-friendly paid content price.',
|
||||
'single' => true,
|
||||
'default' => 0,
|
||||
'show_in_rest' => true,
|
||||
'sanitize_callback' => static function ($value) {
|
||||
return max(0, (float) $value);
|
||||
},
|
||||
'auth_callback' => $post_edit_auth,
|
||||
]);
|
||||
|
||||
foreach ([
|
||||
DomainModel::RESOURCE_DOWNLOAD_COUNT_KEY => 'Resource download count',
|
||||
DomainModel::RESOURCE_VIEW_COUNT_KEY => 'Resource view count',
|
||||
DomainModel::POST_VIEW_COUNT_KEY => 'Generic post view count',
|
||||
] as $meta_key => $description) {
|
||||
register_post_meta('post', $meta_key, [
|
||||
'type' => 'integer',
|
||||
'description' => $description,
|
||||
'single' => true,
|
||||
'default' => 0,
|
||||
'show_in_rest' => true,
|
||||
'sanitize_callback' => 'absint',
|
||||
'auth_callback' => $post_edit_auth,
|
||||
]);
|
||||
}
|
||||
|
||||
register_term_meta('category', 'aksrt_flow', [
|
||||
'type' => 'string',
|
||||
'description' => 'Category flow mode: inherit/blog/cms',
|
||||
'single' => true,
|
||||
'default' => 'inherit',
|
||||
'show_in_rest' => true,
|
||||
'sanitize_callback' => function ($v) {
|
||||
$v = is_string($v) ? $v : 'inherit';
|
||||
return in_array($v, ['inherit', 'blog', 'cms'], true) ? $v : 'inherit';
|
||||
},
|
||||
'auth_callback' => function () {
|
||||
return current_user_can('manage_categories');
|
||||
},
|
||||
]);
|
||||
}
|
||||
public static function sanitize_downloads_meta($value): array {
|
||||
return DomainModel::sanitize_downloads($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 Customizer 小工具实时预览补齐编辑态包裹。
|
||||
*
|
||||
* @param array $params Dynamic sidebar params.
|
||||
* @return array
|
||||
*/
|
||||
public function filter_sidebar_widget_params(array $params): array {
|
||||
if (!is_customize_preview() || empty($params[0]['before_widget']) || empty($params[0]['after_widget'])) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$params[0]['before_widget'] = '<div class="customize-preview-widget-box"><div class="customize-preview-widget-edit"></div>' . $params[0]['before_widget'];
|
||||
$params[0]['after_widget'] = $params[0]['after_widget'] . '</div>';
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册侧边栏
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user