WordPress.org

Make WordPress Core

Opened 23 months ago

Closed 6 months ago

#20861 closed defect (bug) (wontfix)

switch_to_blog() breaks custom post type permalinks

Reported by: sickhippie Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: Multisite Keywords: close
Focuses: Cc:

Description (last modified by SergeyBiryukov)

When using switch_to_blog() and custom post types, there are very strange results when calling the_permalink() or get_permalink(). For reference, we'll say the root site is blog1 and the second site containing the posts is blog2.

Using this code inside the loop:

switch_to_blog( $post->blog_id );
get_permalink();

If the post type is not registered on the current blog, the permalink given will be sitename.com/blog2/slug - when clicking it as href, it brings you the first instance of that slug in the database.

If the post type is registered on the current blog, the permalink given will be sitename.com/blog2/blog1/post-type/slug - this link will 404.

Related issue: #14992

Change History (13)

comment:1 SergeyBiryukov23 months ago

  • Description modified (diff)

comment:3 wonderboymusic18 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

"sitename.com/blog2/blog1/post-type/slug" - in trunk this doesn't happen, I get this: http://wordpress-core/second/stuff/test-me/

comment:4 SergeyBiryukov18 months ago

  • Resolution changed from invalid to worksforme

comment:5 jaroat18 months ago

  • Cc jaroat added
  • Resolution worksforme deleted
  • Status changed from closed to reopened
  • Version 3.3.2 deleted

Sorry - I can clearly reproduce that behaviour in a current (directory-based) multisite-project:

As-Is State:

  • WP 3.4.2
  • Directory bases Multisite installation
  • Custom Post Type "clipping" was registered in all blogs
  • Actual clipping-entries lie in blog_id 2
  • main blog address is "mydomain.tld/blog"
  • blog 2 address is "mydomain.tld/verband"

home-template of main-blog:

switch_to_blog(2);
$clipping_id = get_id_from_some_function();
$clipping_url = get_permalink($clipping_id);
restore_current_blog();

Problem:

$clipping_url / permalink returned is:

http:// mydomain.tld /verband /blog /slug-of-post-type /slug-of-clipping

I narrowed this down to the function get_extra_permastruct (wp-includes/rewrite.php) called in function get_post_permalink (wp-includes/link-template.php), which wrongly prepends "/blog" to all clipping slugs.

get_permalink does of course correctly work in templates of blog 2.

Wild assumption

Seems that get_extra_permastruct does not know that it has to act in the context of blog 2 after using switch_to_blog.

br from Salzburg,

  • Johannes
Version 0, edited 18 months ago by jaroat (next)

comment:6 SergeyBiryukov18 months ago

  • Milestone set to Awaiting Review

comment:7 jaroat18 months ago

Seems that get_permalink for custom post types depends on get_extra_permastruct in wp-includes/rewrite.php and acts wrongly if the target custom post types was registered with the "with_front" parameter (or without: with_front=1 is default).

get_extra_permastruct relies on it's internal var extra_permastructs which doesn't get updated to the new context when calling switch_to_blog.

So all permalinks fetched after switch_to_blog get constructed in the rewrite-context of the original blog calling the function - not the blog context the programmer switched to.

br from Salzburg,

  • Johannes
Last edited 18 months ago by jaroat (previous) (diff)

comment:8 ryanduff13 months ago

  • Cc ryan@… added

comment:9 williamsba113 months ago

  • Cc brad@… added

comment:10 toscho12 months ago

  • Cc info@… added

comment:11 mordauk8 months ago

  • Cc pippin@… added

comment:12 jeremyfelt8 months ago

  • Keywords close added

I can reproduce on current trunk.

Also of note: If the post type is only registered on blog ID 2, and you ask for the permalink from blog ID 1, the default post structure is returned because blog ID 1 is not aware that clippings exists.

I can't imagine a fix for this being possible without every site in a network installation being able to generate the rewrite rules of every other site on demand. With all of the methods available around creating and modifying rewrite rules, this does not seem plausible.

I can start to imagine some creative ways of solving this on individual setups. I think that's more appropriate here.

Suggesting wontfix.

comment:13 jeremyfelt6 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from reopened to closed

Closing as wontfix. No feedback after 8 months and this doesn't seem plausible.

Note: See TracTickets for help on using tickets.