Files
wordpress-theme-aksrt/functions.php
T
kate522andClaude Opus 5 e30de6562c fix(routing): bootstrap permalink structure so fresh installs resolve single posts
A fresh install leaves `permalink_structure` empty, so WordPress snapshots
$wp_rewrite with no post/page permalink rules and every single post resolves
to 404 until someone re-saves Settings -> Permalinks.

The existing mitigation fired too late to help: routing.php wrote the option
and flushed from `init`, but WP_Rewrite was already constructed with the empty
structure, and core defers pre-`wp_loaded` flushes to a `wp_loaded` callback
that regenerates from that stale snapshot. The rewrite_rules option ended up
non-empty but broken, so the 404 persisted on every request.

New \Jio\Core\RewriteBootstrap owns this: on `after_setup_theme` (still inside
wp-settings.php, before wp-blog-header.php parses the query) it calls
$wp_rewrite->set_permalink_structure() — the same API wp-admin/options-permalink.php
uses — which persists the option *and* refreshes the in-memory snapshot, so both
the current request and the rules written for the next one are correct. A
structure an administrator chose is never overridden.

Also consolidates the two duplicated flush sites that lived inline in
functions.php (`after_switch_theme` closure and the `jio_flushed_version`
block, whose `delete_option('rewrite_rules')` forced a needless regenerate),
and drops the now-redundant permalink write from routing.php. The version
stamp moves to `wp_loaded` priority 20 so it sees the complete rule set
instead of the pre-`add_rewrite_rule()` snapshot.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-02 19:50:24 +08:00

428 lines
15 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
/**
* Jio Theme - Main Functions File (v3.2 Restructured)
*
* 精简版入口文件,仅负责:
* 1. 瀹氫箟甯搁噺 & 杈呭姪鍑芥暟(jio_get_setting)
* 2. 2. 加载 bootstrap(自动加载所有模块)
* 3. 3. 初始化单例实例
* 4. 4. 主题激活时刷新重写规则
*
* 业务逻辑已拆分至 inc/core-hooks.php 和各独立类文件。
*
* @package Jio
* @version 3.2.0
*/
defined('ABSPATH') || exit;
define('JIO_VERSION', '3.4.1-dev');
define('JIO_DIR', get_template_directory());
define('JIO_URI', get_template_directory_uri());
// WordPress 6.7+ 会对 after_setup_theme 之前的翻译调用产生 _load_textdomain_just_in_time 通知,
// 此处抑制该通知以避免前台输出 debug 信息。
add_filter('doing_it_wrong_trigger_error', function ($trigger, $function_name) {
if ($function_name === '_load_textdomain_just_in_time') {
return false;
}
return $trigger;
}, 10, 2);
// ============================================================
// 全局辅助函数(必须在类文件加载之前定义)
// ============================================================
if (!function_exists('jio_get_setting')) {
/**
* 获取合并后的主题设置。
* 兼容旧版 jio_settings,以及新版 basic / seo 拆分存储。
*
* @return array
*/
function jio_get_all_settings() {
if (class_exists('\Jio\Settings\Settings')) {
return \Jio\Settings\Settings::get_all();
}
$settings = get_option('jio_settings', array());
return is_array($settings) ? $settings : array();
}
/**
* 获取主题设置项
* @param string $key 璁剧疆閿悕
* @param string $default 榛樿鍊?
* @return mixed
*/
function jio_get_setting($key = '', $default = '') {
$all = jio_get_all_settings();
if (empty($key)) return $all;
return isset($all[$key]) ? $all[$key] : $default;
}
}
// ============================================================
// 加载 Composer 依赖(第三方库 + 主题 PSR-4:Jio\ → src/)
// ============================================================
$composer_autoload = JIO_DIR . '/vendor/autoload.php';
if (!file_exists($composer_autoload)) {
wp_die(
esc_html__('Jio requires Composer dependencies. Run "composer install" in the theme directory.', 'jio'),
esc_html__('Jio theme', 'jio'),
['response' => 500]
);
}
require_once $composer_autoload;
// Theme classes live under src/ and only load via Composer PSR-4.
// Stale vendor/ (e.g. install before composer.json gained "Jio\\") leaves
// autoload_psr4 without Jio\ and fatals on the first DomainModel reference.
if (!class_exists(\Jio\Core\DomainModel::class, true)) {
wp_die(
esc_html__(
'Jio class autoload is incomplete: Jio\\Core\\DomainModel was not found. In the theme directory run "composer install" (or "composer dump-autoload -o"), then clear any opcode cache (opcache_reset / php-fpm reload).',
'jio'
),
esc_html__('Jio theme', 'jio'),
['response' => 500]
);
}
// ============================================================
// 加载 Bootstrap(辅助函数 → 类文件 → 核心钩子)
// ============================================================
require_once JIO_DIR . '/inc/bootstrap.php';
// §3.4 custom_filter: register custom query vars for archive filter
add_filter('query_vars', function ($vars) {
$vars[] = 'jio_filter_cat';
$vars[] = 'jio_filter_tag';
// Dynamic jio_cf_* vars are handled via $_GET fallback in templates
return $vars;
});
// 主题切换离开时:清理本主题注册的 cron 任务
add_action('switch_theme', function () {
$hooks = ['jio_dl_token_cleanup', 'jio_notification_cleanup', 'jio_creator_income_settlement', 'jio_vip_membership_expiry'];
foreach ($hooks as $hook) {
$next = wp_next_scheduled($hook);
while ($next) {
wp_unschedule_event($next, $hook);
$next = wp_next_scheduled($hook);
}
}
});
// ============================================================
// 初始化所有单例实例
// ============================================================
// RewriteBootstrap 的 after_setup_theme 回调需在 Setup 的 init 注册之前入队,
// 让 permalink 快照在主题规则注册后、主查询解析前就已刷新。
\Jio\Core\RewriteBootstrap::get_instance()->init();
\Jio\Core\Setup::get_instance()->init();
\Jio\WidgetSystem\Runtime::init();
\Jio\Core\Scripts::get_instance()->init();
\Jio\Admin\Admin::get_instance()->init();
if (class_exists('\Jio\Admin\NavMenuOptions')) {
\Jio\Admin\NavMenuOptions::init();
}
if (class_exists('\Jio\Admin\PageConfigMetaBox')) {
\Jio\Admin\PageConfigMetaBox::init();
}
\Jio\Auth\OAuth::get_instance()->init();
if (class_exists('\Jio\Auth\WeixinGzh')) {
\Jio\Auth\WeixinGzh::get_instance()->init();
}
if (class_exists('\Jio\Frontend\WeChatShare')) {
\Jio\Frontend\WeChatShare::get_instance()->init();
}
// 初始化代理登录(根据配置模式选择性加载)
$jio_proxy_mode = \Jio\Auth\OAuthProviderCatalog::proxy_mode();
if ($jio_proxy_mode === 'client' && class_exists('\Jio\Auth\OAuthProxyClient')) {
\Jio\Auth\OAuthProxyClient::get_instance()->init();
}
if ($jio_proxy_mode === 'server' && class_exists('\Jio\Auth\OAuthProxyServer')) {
\Jio\Auth\OAuthProxyServer::get_instance()->init();
}
\Jio\Settings\Settings::get_instance()->init();
if (class_exists('\Jio\Settings\MailNotifications')) {
\Jio\Settings\MailNotifications::init();
}
\Jio\Auth\Router::get_instance()->init();
\Jio\Core\Templates::get_instance()->init();
\Jio\Auth\Moderation::get_instance()->init();
if (class_exists('\Jio\Extensions\SecurityHardening')) {
\Jio\Extensions\SecurityHardening::get_instance()->init();
}
if (class_exists('\Jio\Extensions\SystemTools')) {
\Jio\Extensions\SystemTools::get_instance()->init();
}
if (class_exists('\Jio\Frontend\PageAdminSet')) {
\Jio\Frontend\PageAdminSet::get_instance()->init();
}
// 短代码统一注册入口(registry)
if (class_exists('\Jio\Core\Shortcodes')) {
add_action('init', function () {
\Jio\Core\Shortcodes::get_instance()->register();
});
}
// 用户限制/封禁系统
if (class_exists('\Jio\User\Restriction')) {
\Jio\User\Restriction::get_instance()->init();
}
// 用户中心 & 公开主页协调类
if (class_exists('\Jio\User\Center')) {
\Jio\User\Center::get_instance()->init();
}
if (class_exists('\Jio\User\NotificationPreferences')) {
\Jio\User\NotificationPreferences::init();
}
if (class_exists('\Jio\User\BadgeAutoAward')) {
\Jio\User\BadgeAutoAward::get_instance()->init();
}
if (class_exists('\Jio\User\Home')) {
\Jio\User\Home::get_instance()->init();
}
// 数据表迁移器:注册 hook(after_switch_theme + admin_init 双触发)
if (class_exists('\Jio\Core\DBMigrator')) {
\Jio\Core\DBMigrator::init();
}
// 积分获取入口(注册赠送 / 评论奖励 / 签到)
if (class_exists('\Jio\Credits\Earn')) {
\Jio\Credits\Earn::get_instance()->init();
}
if (class_exists('\Jio\Credits\Signin')) {
\Jio\Credits\Signin::get_instance()->init();
}
if (class_exists('Jio\\Payment\\CreatorRevenue')) {
\Jio\Payment\CreatorRevenue::get_instance()->init();
}
if (class_exists('Jio\\Payment\\ReferralAttribution')) {
\Jio\Payment\ReferralAttribution::get_instance()->init();
}
if (class_exists('Jio\\Payment\\CommissionLedger')) {
\Jio\Payment\CommissionLedger::get_instance()->init();
}
if (class_exists('Jio\\Payment\\InviteCode')) {
\Jio\Payment\InviteCode::get_instance()->init();
}
// 支付中心统计的按天缓存:订单状态变化 / 删除时失效(需前后台都挂载,回调不走后台)
if (class_exists('Jio\\Payment\\OrderAnalyticsDaily')) {
\Jio\Payment\OrderAnalyticsDaily::get_instance()->init();
}
if (class_exists('\Jio\Content\Pay')) {
\Jio\Content\Pay::get_instance()->init();
}
if (class_exists('\Jio\Content\VipService')) {
\Jio\Content\VipService::get_instance()->init();
}
if (class_exists('\Jio\Payment\ChargeCard')) {
\Jio\Payment\ChargeCard::get_instance()->init();
}
if (class_exists('\Jio\Payment\OrderCenterRest')) {
\Jio\Payment\OrderCenterRest::get_instance()->init();
}
if (class_exists('\Jio\Ticket\TicketService')) {
\Jio\Ticket\TicketService::get_instance()->init();
}
if (class_exists('\Jio\Credits\BalanceService')) {
\Jio\Credits\BalanceService::get_instance()->init();
}
// Download State & Docs Presenter are pure service singletons (no hooks)
if (class_exists('\Jio\Content\DownloadState')) {
\Jio\Content\DownloadState::get_instance();
}
if (class_exists('\Jio\Core\DocsPresenter')) {
\Jio\Core\DocsPresenter::get_instance();
}
if (class_exists('\Jio\Content\Visibility')) {
\Jio\Content\Visibility::get_instance()->init();
}
if (class_exists('\Jio\Ai\AI')) {
\Jio\Ai\AI::get_instance(); // config-gated; available when admin enables
}
if (class_exists('\Jio\Payment\WeChatNotify')) {
\Jio\Payment\WeChatNotify::get_instance()->init();
}
if (class_exists('\Jio\Core\CommentActions')) {
\Jio\Core\CommentActions::get_instance()->init();
}
if (class_exists('\Jio\Core\GoRedirect')) {
\Jio\Core\GoRedirect::get_instance()->init();
}
if (class_exists('\Jio\Core\PostsNavs')) {
\Jio\Core\PostsNavs::get_instance()->init();
}
if (class_exists('\Jio\Identity\Identity')) {
\Jio\Identity\Identity::get_instance()->init();
}
if (class_exists('\Jio\User\AuthApply')) {
\Jio\User\AuthApply::get_instance()->init();
}
if (class_exists('\Jio\User\BanAppeal')) {
\Jio\User\BanAppeal::get_instance()->init();
}
if (class_exists('\Jio\Messages\SiteNotice')) {
\Jio\Messages\SiteNotice::get_instance()->init();
}
if (class_exists('\Jio\Extensions\APIAudit')) {
\Jio\Extensions\APIAudit::get_instance()->init();
}
if (class_exists('\Jio\Extensions\MeiliSearch')) {
\Jio\Extensions\MeiliSearch::get_instance()->init();
// Async single post index (debounced)
add_action('jio_meilisearch_index_single', function (int $post_id) {
\Jio\Extensions\MeiliSearch::get_instance()->index_post($post_id);
});
}
if (class_exists('\Jio\Extensions\SearchPush')) {
\Jio\Extensions\SearchPush::get_instance()->init();
}
if (class_exists('\Jio\Extensions\SearchPushMetaBox')) {
\Jio\Extensions\SearchPushMetaBox::get_instance()->init();
}
if (class_exists('\Jio\Core\SEOHead')) {
\Jio\Core\SEOHead::get_instance()->init();
}
if (class_exists('\Jio\Core\UpdateChecker')) {
\Jio\Core\UpdateChecker::get_instance()->init();
}
if (class_exists('\Jio\Core\CategoryRewrite')) {
\Jio\Core\CategoryRewrite::get_instance()->init();
}
if (class_exists('\Jio\Core\FrontSubmit')) {
\Jio\Core\FrontSubmit::get_instance()->init();
}
if (class_exists('\Jio\Attachment\UploadLimits')) {
\Jio\Attachment\UploadLimits::get_instance()->init();
}
if (class_exists('\Jio\Attachment\PendingUploads')) {
\Jio\Attachment\PendingUploads::get_instance()->init();
}
// Register built-in payment gateways
if (class_exists('\Jio\Payment\Gateway')) {
$gw = \Jio\Payment\Gateway::get_instance();
// 注册支付回调路由(/payment/{gateway}/notify|return|cancel)。
$gw->init();
if (class_exists('\Jio\Payment\BalanceGateway')) {
$gw->register('balance', new \Jio\Payment\BalanceGateway());
}
if (class_exists('\Jio\Payment\Gateways\AlipayGateway')) {
$gw->register('alipay', new \Jio\Payment\Gateways\AlipayGateway());
}
if (class_exists('\Jio\Payment\Gateways\WechatPayGateway')) {
$gw->register('wechatpay', new \Jio\Payment\Gateways\WechatPayGateway());
}
if (class_exists('\Jio\Payment\Gateways\PayPalGateway')) {
$gw->register('paypal', new \Jio\Payment\Gateways\PayPalGateway());
}
if (class_exists('\Jio\Payment\Gateways\StripeGateway')) {
$gw->register('stripe', new \Jio\Payment\Gateways\StripeGateway());
}
if (class_exists('\Jio\Payment\Gateways\EpayGateway')) {
$gw->register('epay_alipay', new \Jio\Payment\Gateways\EpayGateway('alipay'));
$gw->register('epay_wxpay', new \Jio\Payment\Gateways\EpayGateway('wxpay'));
}
do_action('jio_register_payment_gateways', $gw);
}
if (class_exists('\Jio\Core\ResourceMetaBox')) {
\Jio\Core\ResourceMetaBox::get_instance()->init();
}
// 分类/标签局部配置(term meta 字段)
if (class_exists('\Jio\Core\TermMeta')) {
\Jio\Core\TermMeta::get_instance()->init();
}
// 文章局部配置 meta box(仅后台)
if (is_admin() && class_exists('\Jio\Core\PostMetaBox')) {
\Jio\Core\PostMetaBox::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Core\SEOMetaBox')) {
\Jio\Core\SEOMetaBox::get_instance()->init();
}
// 绔欑偣璁块棶閲忕粺璁?
if (class_exists('\Jio\Core\StatsTracker')) {
\Jio\Core\StatsTracker::init();
}
// WordPress 原生"用户"菜单:积分管理
if (class_exists('\Jio\User\CreditsAdmin')) {
\Jio\User\CreditsAdmin::get_instance()->init();
}
if (class_exists('\Jio\User\BalanceAdmin')) {
\Jio\User\BalanceAdmin::get_instance()->init();
}
if (class_exists('\Jio\User\Badges')) {
\Jio\User\Badges::get_instance()->init();
}
if (class_exists('\Jio\User\BadgesAdmin')) {
\Jio\User\BadgesAdmin::get_instance()->init();
}
if (class_exists('\Jio\User\Level')) {
\Jio\User\Level::get_instance()->init();
}
if (class_exists('\Jio\User\LevelAdmin')) {
\Jio\User\LevelAdmin::get_instance()->init();
}
if (class_exists('\Jio\User\ProfileAdmin')) {
\Jio\User\ProfileAdmin::init();
}
if (class_exists('\Jio\User\Metrics')) {
\Jio\User\Metrics::get_instance()->init();
}
// WordPress 原生侧栏:支付/订单运营中心(legacy jiopay 对齐)
if (is_admin() && class_exists('\Jio\Admin\Native\PayMenus')) {
\Jio\Admin\Native\PayMenus::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Admin\Native\PayCoupons')) {
\Jio\Admin\Native\PayCoupons::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Admin\Native\PayChargeCards')) {
\Jio\Admin\Native\PayChargeCards::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Admin\Native\PayOrders')) {
\Jio\Admin\Native\PayOrders::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Admin\Native\PayProducts')) {
\Jio\Admin\Native\PayProducts::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Admin\Native\PayWithdrawals')) {
\Jio\Admin\Native\PayWithdrawals::get_instance()->init();
}
if (is_admin() && class_exists('\Jio\Admin\Native\PayIncome')) {
\Jio\Admin\Native\PayIncome::get_instance()->init();
}
// 后台文章列表增强:互动/销售数据列 + 快捷编辑配置项
if (is_admin() && class_exists('\Jio\Admin\Native\PostListEnhance')) {
\Jio\Admin\Native\PostListEnhance::get_instance()->init();
}
// WordPress 原生用户菜单:消息/推广码/认证/禁封(legacy users.php 子菜单对齐)
if (is_admin() && class_exists('\Jio\Admin\Native\UsersMenus')) {
\Jio\Admin\Native\UsersMenus::get_instance()->init();
}
// ============================================================
// 主题删除时的数据库清理(仅在用户启用清理选项时生效)
// uninstall.php 会检查 jio_cleanup_on_uninstall 选项
// ============================================================
register_deactivation_hook(__FILE__, function () {
// 主题停用时不做任何清理,仅在删除时由 uninstall.php 处理。
// 自定义表(jio_*)在主题切换后保留数据,确保重新启用时不丢失。
});