WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 21 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 @SergeyBiryukov3 years ago

  • Description modified (diff)

comment:3 @wonderboymusic3 years 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 @SergeyBiryukov3 years ago

  • Resolution changed from invalid to worksforme

comment:5 @jaroat3 years 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 based 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
Last edited 3 years ago by jaroat (previous) (diff)

comment:6 @SergeyBiryukov3 years ago

  • Milestone set to Awaiting Review

comment:7 @jaroat3 years 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_permastructspost-type-name? 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
Version 0, edited 3 years ago by jaroat (next)

comment:8 @ryanduff2 years ago

  • Cc ryan@… added

comment:9 @williamsba12 years ago

  • Cc brad@… added

comment:10 @toscho2 years ago

  • Cc info@… added

comment:11 @mordauk23 months ago

  • Cc pippin@… added

comment:12 @jeremyfelt23 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 @jeremyfelt21 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.