WordPress.org

Make WordPress Core

Opened 2 years ago

Last modified 3 weeks ago

#23221 reopened defect (bug)

Multisite in subdirectory with root site address

Reported by: grapplerulrich Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 3.5
Component: Bootstrap/Load Keywords: dev-feedback
Focuses: multisite Cc:

Description

I have seem to have found a url bug in the multisite.

How to replicate

  1. Install WordPress in a subdirectory
  2. Change the the url from the subdirectory to the root by adding index.php to the the root and changing the following code.
    /** Loads the WordPress Environment and Template */
    require('./subdirectory/wp-blog-header.php');
    
  3. Change the site url in the settings to the root.
  4. Start the process to convert the site to a multisite.

Affect

Then it should cause the network dashboard url to be incorrect. You will get http://example.com/wp-admin/network/ instead of
http://example.com/subdirectory/wp-admin/network/.

Attachments (2)

23221.diff (609 bytes) - added by markoheijnen 2 years ago.
Replace build url with site_url()
23221.2.diff (637 bytes) - added by markoheijnen 2 years ago.
Should not have used site_url for this

Download all attachments as: .zip

Change History (35)

comment:1 @alexvorn22 years ago

  • Cc alexvornoffice@… added

comment:3 @odisant2 years ago

Problem seems to be in network_site_url() in link-template.php. Changing line 2112 from:

$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );

to:

$url = set_url_scheme( trailingslashit(site_url()), $scheme );

Seems to resolve the problem.

@markoheijnen2 years ago

Replace build url with site_url()

comment:4 @markoheijnen2 years ago

  • Milestone changed from Awaiting Review to 3.6

Added a patch to solve the problem with the help of site_url what odisant mentioned. Would love to see this in 3.6.

comment:5 @markoheijnen2 years ago

  • Keywords has-patch added; needs-patch removed

@markoheijnen2 years ago

Should not have used site_url for this

comment:6 @markoheijnen2 years ago

Added a patch that does work. I don't think get_site_option() will cost a performance penalty since it does get cached.

comment:7 @markoheijnen22 months ago

  • Keywords has-patch removed
  • Milestone 3.6 deleted
  • Resolution set to invalid
  • Status changed from new to closed

Closing as invalid. Reason is that the path isn't correctly set.

So check the following

  • PATH_CURRENT_SITE is something like /wp/
  • All rows of wp_blogs don't have the path like /wp/
  • Path of the site in wp_site
  • siteurl in wp_sitemeta
  • siteurl of the single site in wp_options of wp_x_options

comment:8 @nacin22 months ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

The path is set correctly. This isn't invalid, rather, this is by design. The root site uses /wordpress for siteurl, but a network requires URL rewriting, and in that context we are able to simply rewrite the subdirectory out of all subsequent sites (and the network admin).

comment:9 @SergeyBiryukov22 months ago

  • Milestone set to Awaiting Review

comment:10 @SergeyBiryukov22 months ago

#24382 was marked as a duplicate.

comment:11 @creativeinfusion22 months ago

Sorry about the duplicate, I thought this ticket was just a misconfiguration of a straight MS subdirectory install where the home directory was the subdirectory.

There's definately a good case for tidy URLs, but we're left with no function that can be relied on to tell us the actual URL to the site install. Even using site_url(BLOG_ID_CURRENT_SITE) may not work - see Nacin's point in comment:78:ticket:19796

Having network_site_url() & network_home_url() return the same value when the underlying subdir network install isn't actually like that is certainly odd. Until it was possible to install a sub directory MS in its own directory it delivered expected results all the time. Expressing that install difference is what I thought the different functions were for (mirroring site_url and home_url on single site).

comment:12 @markoheijnen22 months ago

I was sure that was the case since I tested it out and with setting all table fields correctly I could solve this issue. But it was strange that I had to do that manually if it was needed at all.

comment:13 @creativeinfusion22 months ago

For a sub directory install PATH_CURRENT_SITE will be set as you noted, but for a sub directory install where WordPress is given its own directory and the site operates from document root, PATH_CURRENT_SITE is not set.

PATH_CURRENT_SITE is equivilent to the path component of home_url on a single site install.

comment:14 @andre.langer21 months ago

sorry, I am a little bit confused now.
Is there already a working, proper solution or patch for the mentioned issue in WordPress 3.5.1?

I have just done a clean install of Wordpress in an own directory different from the root directory and enabled Multisite (subdirectory) behavior. I can also not access the network administrator dashboard because the generated admin URL does not contain the mainsite subdirectory before wp_admin, which redirects me back to the frontend site of the original Wordpress installation giving a 404 for wp_admin/network.

The network wizard generated a config template with PATH_CURRENT_SITE set to "/".
Some people suggested to edit wp-includes/link-template.php func network_admin_url(),
but this is said to be an inappropriate solution in this thread.

Version 0, edited 21 months ago by andre.langer (next)

comment:15 @creativeinfusion21 months ago

I have several installations using WordPress Multisite 3.5.1 (subdirectory) with WordPress in it's own directory and it does work fine. There's no need to edit any core code.

You do have to make the advised changes to your .htaccess (or web.config if on IIS) as per your sites the network install page instructions, or it can't work. See also http://codex.wordpress.org/Multisite_Network_Administration#.htaccess_and_Mod_Rewrite

The only issue is if you use custom content/plugin directories, then you'll need to make custom rewrite rules.

Last edited 21 months ago by creativeinfusion (previous) (diff)

comment:16 @jeremyfelt14 months ago

  • Component changed from Multisite to Bootstrap/Load
  • Focuses multisite added

comment:17 @Denis-de-Bernardy13 months ago

  • Keywords dev-feedback added

@Nacin or other core dev: Any traction to fix this in 3.9? I'm working on a BuddyPress site which I'd like to install using this setup. A cursory look into what's wrong atm suggests me that I can get most or all of the problems fixed using a plugin, but we might as well check this into Core if there's some traction from code devs.

comment:18 @Denis-de-Bernardy13 months ago

For reference, besides the installer (which creates incorrect URIs on the initial site that then need fixing in the database), the fix seems to be the following with a site installed in /wp and wp content residing in /content:

wp-config:

define('WP_CONTENT_DIR', __DIR__ . '/content');
define('WP_CONTENT_URL', 'http://www.example.com/content');

define('WP_ALLOW_MULTISITE',    true);

define('MULTISITE',             true);
define('SUBDOMAIN_INSTALL',     false);
define('DOMAIN_CURRENT_SITE',   'www.example.com');
define('PATH_CURRENT_SITE',     '/');
define('SITE_ID_CURRENT_SITE',  1);
define('BLOG_ID_CURRENT_SITE',  1);

.htaccess:

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(content/.*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) wp/$2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ wp/$2 [L]
RewriteRule . index.php [L]

content/mu-plugins/ms-fixes.php:

<?php
register_theme_directory(ABSPATH . 'wp-content/themes/');

add_filter('network_site_url', function($url, $path, $scheme) {
    return str_replace(
        '//www.example.com/wp-admin/network/',
        '//www.example.com/wp/wp-admin/network/',
        $url);
}, 10, 3);

WP insists on making the original site's admin area live in /wp/ and I'm actually fine with that. I'll post updates and patches in here if I find more issues/fixes if the ticket gets blessed by a core dev.

Last edited 13 months ago by Denis-de-Bernardy (previous) (diff)

comment:19 follow-ups: @nacin13 months ago

We added WP-in-subdirectory support to multisite in 3.5. It doesn't actually put /wp/ in URLs, though. Rather, since we require URL rewriting for multisite, we simply rewrite the /wp/ out of those URLs. Thus, nothing changes and it's still /wp-admin/network/ etc. If we have to rewrite the heck out of those URLs anyway, we might as well also rewrite out the subdirectory.

If you have a single site with home != siteurl and try to promote it to a multisite, this should 'just work.' You should be given the right .htaccess rules and everything should be good.

If you wish to keep /wp/, you'll need a filter and changes to your .htaccess. I don't think we need to support that out of the box.

comment:20 in reply to: ↑ 19 @Denis-de-Bernardy13 months ago

Replying to nacin:

Thus, nothing changes and it's still /wp-admin/network/ etc.

That one returned an internal server error, though I admittedly didn't check if it still did after editing the rewrite rules.

If you have a single site with home != siteurl and try to promote it to a multisite, this should 'just work.'

It doesn't. It sets some entries in wp_site and wp_blogs or wp_options to the /wp/ url; I had to edit the database to make it work. Or it might be that it hadn't, and I edited them before changing the rewrite rules, and then it eventually did.

Uploads didn't work out of the box for the same reason (they do now, admittedly)

If you wish to keep /wp/, you'll need a filter and changes to your .htaccess. I don't think we need to support that out of the box.

Your call.

Last edited 13 months ago by Denis-de-Bernardy (previous) (diff)

comment:21 @Denis-de-Bernardy13 months ago

Upon investigating this further:

The rewrite rules that WP generates, and the entries in wp_site and wp_blogs, are all correct provided that #26969 gets fixed. Once that gets committed, it's pretty safe to close this.

Using a custom content folder works fine provided #24143 gets fixed. It then worked with WP_CONTENT_DIR set to wp-content and content.

There *is* potential for a very minor and mildly related issue when a theme with an identical slug lives in /wp-content/themes/foo and /wp/wp-content/themes/foo, with the latter active (it'll then load files from the former). This is assuming WP allows either to be active (I haven't tested for this).

There's potential for a last tweak related to the main site's wp-admin area: before the network setup, the siteurl is set to http://example.com/wp. It should ideally get changed to http://example.com during the network setup. Needs dev feedback here.

Last edited 13 months ago by Denis-de-Bernardy (previous) (diff)

comment:22 @Denis-de-Bernardy13 months ago

Another related plugin is: #17376.

comment:23 @ircbot13 months ago

This ticket was mentioned in IRC in #wordpress-dev by ddebernardy. View the logs.

comment:24 @Denis-de-Bernardy13 months ago

There actually also are issues with uploads. See #25650 for instance. And trying to place the uploads folder anywhere but in WP_CONTENT_DIR . '/uploads' borders on the impossible.

comment:25 @Denis-de-Bernardy13 months ago

For the uploads folder, a mu-plugin and a rewrite rule actually do the trick, e.g. for /media that would be:

RewriteRule ^([_0-9a-zA-Z-]+/)?(media/.*) $2 [L]
add_filter('pre_option_upload_path', function($val) {
	return '../media';
});
add_filter('pre_option_upload_url_path', function($val) {
	$media_url = home_url('/media');
	$media_url = preg_replace("#^.*?//[^/]+#", '', $media_url);
	return $media_url;
});

Can anyone picture how this could get fixed properly in WP?

comment:26 @CreativeInfusion13 months ago

Related: #23483 (for UPLOADS)

comment:27 @danielbachhuber12 months ago

This caused me some amount of hell the last few days — it would be great to get fixed up.

Here's the intermediate solution I used for my situation: https://gist.github.com/danielbachhuber/9379135

Our setup is:

  • One subdomain network
  • WordPress is installed in /wp/

I also ran into #27287

comment:28 in reply to: ↑ 19 @FolioVision7 weeks ago

Replying to nacin:

If you wish to keep /wp/, you'll need a filter and changes to your .htaccess. I don't think we need to support that out of the box.

Nacin, this seems to me an arrogant and short-sighted approach. You could just fix the network_admin_url() function out of the box. It's one line in wp-config.php.

I know it's more exciting to code really complex features which bloat Wordpress than to make core URL structure both flexible and bulletproof. I'd say the second is more important.

Enjoy the hoops you make people jump through. Could you just fix network_admin_url(). We've done the hard work for you.

Last edited 7 weeks ago by FolioVision (previous) (diff)

comment:29 @alexander.rohmann6 weeks ago

Just spent several hours trying to sort this out before coming across this. I don't see how "site URL" should ever depend on "path"

I think it's fair to expect network_site_url to return the actual site url, just like site_url would. Meaning the URL to the WordPress files themselves. Would be really great if this and #27287 could be addressed. Some workarounds are ok, but would be so much simpler if this was just done right in core.

I propose adding a new constant that specifies the WordPress files location. Something like:

define('WP_INSTALL_PATH','/wp/');

The path can still be used as a safe fallback, but this way we can have a Multisite and separate the install files without needing to bother with extra code.

Thoughts?

comment:30 @FolioVision6 weeks ago

Hi Alexander,

Thanks for taking a close look at this issue.

On the other hand, adding a clear cut path to the Wordpress PHP files would really simplify matters in multisite. My vote is for adding this simple universal variable which would be accessed in all multisite, just like you suggested:

define('WP_INSTALL_PATH','/wp/');

Alec Kinnear

PS. I had thought network_admin_url() would get the job done using the existing path variables.

Last edited 6 weeks ago by FolioVision (previous) (diff)

comment:31 @nacin3 weeks ago

#31057 was marked as a duplicate.

comment:32 @SergeyBiryukov3 weeks ago

#31057 was marked as a duplicate.

comment:33 @nacin3 weeks ago

Essentially, we made a decision in #19796 that having /wp/ in the URL was ugly. But everything still works. Let me explain:

Single site has no requirement for rewrite rule support in Apache, IIS, nginx, etc. Multisite, however, does. So for single site, you have home URL being example.com and site URL being example.com/wp/, where the files are. But in multisite, we can keep the files in example.com/wp/wp-admin/ (for example), set the URLs to example.com/wp-admin/, then use rewrite rules to rewrite /wp-admin/ to /wp/wp-admin/. This keeps URLs clean and the filesystem clean.

We use this setup on wordpress.org. It works fine. Something like https://gist.github.com/danielbachhuber/9379135 is only necessary if you want /wp/ in the URL. If you do not, then when you set up a network with /wp/ being your site URL, everything will be handled for you in the rewrite rules that are generated.

Note: See TracTickets for help on using tickets.