[wp-trac] [WordPress Trac] #21824: Custom Post Type Permalink Rules Are Not Updated Correctly When Saving Changes
WordPress Trac
wp-trac at lists.automattic.com
Thu Sep 6 16:56:13 UTC 2012
#21824: Custom Post Type Permalink Rules Are Not Updated Correctly When Saving
Changes
--------------------------+-----------------------------
Reporter: MarcusPope | Owner:
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Permalinks | Version:
Severity: normal | Keywords:
--------------------------+-----------------------------
When changing permalink structures using Common Settings or Custom
Structure, clicking Save Changes will only update core system rewrite
rules. Custom Post Type rewrite rules are re-used from the previous
setting. If you click save changes twice the correct rewrite rules are
updated and used.
If you only save once, canonical.php will step in and issue a 301 redirect
to the appropriate post. But if you save twice it doesn't have to do any
work at all. This is actually causing an infinite 301 redirect with one
of my plugins. I have a fix to prevent the recursion, but it still means
it cannot find my custom post type content until I update the permalinks
settings again. This behavior occurs whether you register post types in
"init" or in a theme's functions.php or in a plugin.
I've seen multiple core devs and users say off-handedly that you should
save the page once or twice as seen in these links:
http://wordpress.org/support/topic/permalinks-go-404-on-custom-post-
types?replies=7#post-2301522
http://wordpress.org/support/topic/plugin-custom-post-type-permalinks-all-
custom-post-type-pages-and-categories-result-in-
404s?replies=12#post-2841550
http://wordpress.stackexchange.com/a/40591/10127
http://wordpress.org/support/topic/custom-post-type-permalink-
rewrite?replies=10
The reason this behavior occurs is because `flush_rewrite_rules()` doesn't
actually flush custom post type rewrite rules stored in
`WP_Rewrite::$extra_permastructs`. `WP_Rewrite::init()` will only reset
internal core posts/pages/category/etc structures. And
`$extra_permastructs` rules are created on `register_post_type()` which
occurs before the form post to options-permalink.php has a chance to
update the `structure` and `$front` values.
So order of execution is:
1. Change Permalink Structure and Page Post to options-permalink.php
1. Read structure setting from database
1. Load system permalinks
1. Load plugins and register their permalinks
1. options-permalink updates the structure setting value in the database
1. Calls flush system permalinks
1. Loads new system permalinks and merges with old CPT permalinks because
it never calls `register_post_type()`
On a second save, step 4 will have the correct permalinks structure, so
when they are merged with the already correct system permalinks all is
well with the universe again.
Ideally `flush_rewrite_rules()` actually flushes all rewrite rules. But
I'm not sure if calling `register_post_type()` twice in one page load is
safe. It could do an ajax post for the first change, and then a full form
post for custom post types - but that seems a little hackey. I don't have
a good solution yet so I can't provide a patch.
To reproduce and debug this behavior, setup at least one CPT and dump the
variable `$this->rules` at the end of the function `rewrite_rules()` in
rewrite.php. Go into permalinks settings page, change your structure to
Numeric, click save. The log file will list all of the rules but the CPT
will not have "archives" in front of their URL (unless Numeric was already
selected.) Now select a different structure - "Post name", click save,
and the CPT urls will have "archives" in front of the url, but the others
will not. Click save again, and CPT's will be fixed.
Thanks,
Marcus
--
Ticket URL: <http://core.trac.wordpress.org/ticket/21824>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list