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'), ]); } /** * 注册自定义文章类型 * * v3.4: 移除 aksrt_resource CPT,资源元数据统一挂在 post 上, * 通过 _aksrt_is_resource meta 标记单篇文章是否为“资源”。 */ public function register_post_types(): void { // Shop rewrite settings (safe fallback if settings not yet loaded) $shop_rewrite = []; if (class_exists('AKSRT_Settings')) { $shop = AKSRT_Settings::get_shop_settings(); $shop_rewrite = $shop['rewrite'] ?? []; } $product_slug = sanitize_key((string) ($shop_rewrite['product_slug'] ?? 'product')); $suffix_html = !empty($shop_rewrite['suffix_html']); // 商品 CPT register_post_type('aksrt_product', [ '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_rest' => true, 'has_archive' => true, 'hierarchical' => false, 'supports' => ['title', 'editor', 'excerpt', 'thumbnail', 'author', 'revisions'], 'rewrite' => ['slug' => $product_slug, 'with_front' => false], 'capability_type' => 'post', 'map_meta_cap' => true, ]); // 商品分类 taxonomy(独立于文章 category) register_taxonomy('aksrt_product_cat', 'aksrt_product', [ 'labels' => [ 'name' => __('商品分类', 'aksrt'), 'singular_name' => __('商品分类', 'aksrt'), 'search_items' => __('搜索商品分类', 'aksrt'), 'all_items' => __('所有商品分类', 'aksrt'), 'parent_item' => __('父级分类', 'aksrt'), 'edit_item' => __('编辑分类', 'aksrt'), 'add_new_item' => __('新增分类', 'aksrt'), 'menu_name' => __('商品分类', 'aksrt'), ], 'public' => true, 'hierarchical' => true, 'show_ui' => false, 'show_in_rest' => true, 'show_admin_column' => false, 'rewrite' => ['slug' => 'product-cat', 'with_front' => false], ]); // 商品标签 taxonomy(独立于文章 post_tag) register_taxonomy('aksrt_product_tag', 'aksrt_product', [ 'labels' => [ 'name' => __('商品标签', 'aksrt'), 'singular_name' => __('商品标签', 'aksrt'), 'search_items' => __('搜索商品标签', 'aksrt'), 'all_items' => __('所有商品标签', 'aksrt'), 'edit_item' => __('编辑标签', 'aksrt'), 'add_new_item' => __('新增标签', 'aksrt'), 'menu_name' => __('商品标签', 'aksrt'), ], 'public' => true, 'hierarchical' => false, 'show_ui' => false, 'show_in_rest' => true, 'show_admin_column' => false, 'rewrite' => ['slug' => 'product-tag', 'with_front' => false, ], ]); // 项目展示 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', AKSRT_Domain_Model::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', AKSRT_Domain_Model::PAY_META_KEY, [ 'type' => 'object', 'description' => 'Canonical paid content payload.', 'single' => true, 'default' => AKSRT_Domain_Model::default_pay_meta(), 'show_in_rest' => [ 'schema' => [ 'type' => 'object', 'properties' => [ 'pay_type' => [ 'type' => 'string', 'enum' => array_keys(AKSRT_Domain_Model::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' => [AKSRT_Domain_Model::class, 'sanitize_pay_meta'], 'auth_callback' => $post_edit_auth, ]); register_post_meta('post', AKSRT_Domain_Model::PAY_TYPE_KEY, [ 'type' => 'string', 'description' => 'Query-friendly paid content type.', 'single' => true, 'default' => AKSRT_Domain_Model::PAY_TYPE_NO, 'show_in_rest' => true, 'sanitize_callback' => [AKSRT_Domain_Model::class, 'normalize_pay_type'], 'auth_callback' => $post_edit_auth, ]); register_post_meta('post', AKSRT_Domain_Model::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 ([ AKSRT_Domain_Model::RESOURCE_DOWNLOAD_COUNT_KEY => 'Resource download count', AKSRT_Domain_Model::RESOURCE_VIEW_COUNT_KEY => 'Resource view count', AKSRT_Domain_Model::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 AKSRT_Domain_Model::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'] = '
' . $params[0]['before_widget']; $params[0]['after_widget'] = $params[0]['after_widget'] . '
'; return $params; } /** * 注册侧边栏 */ } return AKSRT_Setup::get_instance();