Files
wordpress-theme-aksrt/src/Core/Setup.php
T

291 lines
12 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
/**
* @package AKSRT
*/
namespace AKSRT\Core;
defined('ABSPATH') || exit;
class Setup {
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_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);
// 内容宽度(用于区块编辑器)
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()),
],
'pay_modo' => ['type' => 'string', 'enum' => ['0', 'points']],
'price' => ['type' => 'number'],
'points_price' => ['type' => 'integer'],
'original_price' => ['type' => 'number'],
'vip1_price' => ['type' => 'number'],
'vip2_price' => ['type' => 'number'],
'vip1_points' => ['type' => 'integer'],
'vip2_points' => ['type' => 'integer'],
'pay_limit' => ['type' => 'integer', 'enum' => [0, 1, 2]],
'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;
}
/**
* 注册侧边栏
*/
}