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 -9
View File
@@ -189,20 +189,14 @@ add_action('init', function () {
}
// 统一 flush 检查 — bump when user-home rewrite / author override changes
// 固定链接结构的兜底写入由 \Jio\Core\RewriteBootstrap 负责(after_setup_theme),
// 此处只关心本模块自己的规则版本与规则缺失。
$rewrite_version = JIO_VERSION . ':message-routing:' . jio_get_messages_rewrite_slug();
$flushed = get_option('jio_user_rules_flushed');
$rules = get_option('rewrite_rules');
$need_flush = ($flushed !== $rewrite_version)
|| !is_array($rules)
|| $rules === []
|| !get_option('permalink_structure');
// Dev/plain installs often have empty permalink_structure → pretty /user/ 404s at Apache.
// Force a usable structure so registered rewrite rules actually apply.
if (!get_option('permalink_structure')) {
update_option('permalink_structure', '/%postname%/');
$need_flush = true;
}
|| $rules === [];
if ($need_flush) {
flush_rewrite_rules(true);