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>
428 lines
15 KiB
PHP
428 lines
15 KiB
PHP
<?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_*)在主题切换后保留数据,确保重新启用时不丢失。
|
||
});
|