Opened 12 months ago

Last modified 5 weeks ago

#20861 reopened defect (bug)

switch_to_blog() breaks custom post type permalinks

Reported by: sickhippie Owned by:
Priority: normal Milestone: Awaiting Review
Component: Multisite Version:
Severity: normal Keywords:
Cc: jaroat, ryan@…, brad@…, info@…

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 (10)

  • Description modified (diff)
  • 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/

  • Resolution changed from invalid to worksforme
  • 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 7 months ago by jaroat (previous) (diff)
  • Milestone set to Awaiting Review

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 7 months ago by jaroat (previous) (diff)
  • Cc ryan@… added
  • Cc brad@… added
  • Cc info@… added
Note: See TracTickets for help on using tickets.