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>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-02 19:50:24 +08:00
1 parent 39aed0d430
commit e30de6562c
5 files changed
+334 -25

No files matched your search

+3 -16
View File
@@ -94,13 +94,6 @@ if (!class_exists(\Jio\Core\DomainModel::class, true)) {
// ============================================================
require_once JIO_DIR . '/inc/bootstrap.php';
// ============================================================
// 主题激活时刷新重写规则
// ============================================================
add_action('after_switch_theme', function () {
flush_rewrite_rules();
});
// §3.4 custom_filter: register custom query vars for archive filter
add_filter('query_vars', function ($vars) {
$vars[] = 'jio_filter_cat';
@@ -121,18 +114,12 @@ add_action('switch_theme', function () {
}
});
// 兜底:检测版本变更时自动刷新重写规则
if (get_option('jio_flushed_version') !== JIO_VERSION) {
delete_option('rewrite_rules');
add_action('init', function () {
flush_rewrite_rules();
update_option('jio_flushed_version', JIO_VERSION);
}, 99);
}
// ============================================================
// 初始化所有单例实例
// ============================================================
// 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();