[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