[wp-hackers] Permalinks, Custom Post Types & Canonical 301 Redirects...

Marcus Pope Marcus.Pope at springbox.com
Wed Sep 5 23:01:23 UTC 2012


I think I found a bug in WP Core wrt permalinks and custom post types.  If I go into Admin > Settings > Permalinks and change the structure from Post Name to Numeric, all of the rewrite rules are updated with /archives prepended to the rule except for the rules for Custom Post Types.  They are stored in $extra_permastructs of the WP_Rewrite class.  They are initialized on class load to an empty array, and populated with the permalinks specified by the CPT logic when they are loaded with register_post_type().  But those events occur before the update permalink logic in options-permalink.php (near line 86)

And flush_rewrite_rules() doesn't actually re-initialize those CTP permalink rules, it only flushes wp core rewrite rules pertaining to pages posts feeds and the like.  WP_Rewrite simply re-uses the CPT rules as they were loaded on the page post to options-permalink.php.  Which of course means it will use the old version of the rewrite template because it had yet to be updated.

The same issue occurs if you switch back to "Post Name" for the url structure.  Everything updates to use /post_name/ except for custom post types which now contain "archives" in front of the permalink structure.

Clicking save twice after changing the setting will update pages and posts in addition to custom post types.  And I've seen suggestions from Andrew Nacin and others in various other posts to "click save once or twice just to be sure"  when other people have had similar yet different problems, as seen in these top google results:

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

What's crazy is that until the permalinks are "fixed" canonical.php takes over and does 301 redirects for those links that cannot find Custom Post Type content because of the invalid/old rewrite rules.  Whereas if the permalinks are updated twice in a row, redirect_canonical() never has to execute.

I know making "Save Permalinks" execute itself twice in a row would solve the problem (perhaps an ajax request would be better suited than a page post.)  - But that that's as hacky as relying on 301 redirects to correct outdated permalinks because they were loaded too early in the call stack.  Can I reload plugins after already loading them once?  Then we could clear the $extra_permastructs array along with other structures in the init() function, and reload them with the updated $front value.

Obviously this is some deep core stuff, and I'm trying to summarize about 1500 lines of code into a couple paragraphs but is anyone able to shed some light on this problem?  Or at least confirm that it's a problem and that I'm on the right track?

Thanks,
Marcus




More information about the wp-hackers mailing list