WordPress.org

Make WordPress Core

Opened 18 months ago

Last modified 4 months 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 15 months ago.
Replace build url with site_url()
23221.2.diff (637 bytes) - added by markoheijnen 15 months ago.
Should not have used site_url for this

Download all attachments as: .zip

Change History (29)

comment:1 alexvorn218 months ago

  • Cc alexvornoffice@… added

comment:3 odisant16 months 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.

markoheijnen15 months ago

Replace build url with site_url()

comment:4 markoheijnen15 months 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 markoheijnen15 months ago

  • Keywords has-patch added; needs-patch removed

markoheijnen15 months ago

Should not have used site_url for this

comment:6 markoheijnen15 months 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 markoheijnen14 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 nacin14 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 SergeyBiryukov14 months ago

  • Milestone set to Awaiting Review

comment:10 SergeyBiryukov14 months ago

#24382 was marked as a duplicate.

comment:11 creativeinfusion14 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 markoheijnen14 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 creativeinfusion14 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.langer13 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.
It is not only related to the wp-admin rewrite process, I also cannot access the frontend of a created multisite, the generated URL regularly points to http://domain.com/multisitesubdirectory, do I have to declare the wordpress subdir also when creating a new multisite (in comparison to the administration of wordpress url vs site url).

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. Currently, I am still not entirely sure if it is a user configuration error, or if the combination of wordpress subdirectory installation and multisite subdirectory configuration is cleanly supported in Wordpress 3.5.

Version 2, edited 13 months ago by andre.langer (previous) (next) (diff)

comment:15 creativeinfusion13 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 13 months ago by creativeinfusion (previous) (diff)

comment:16 jeremyfelt6 months ago

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

comment:17 Denis-de-Bernardy5 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-Bernardy5 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 5 months ago by Denis-de-Bernardy (previous) (diff)

comment:19 follow-up: nacin5 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-Bernardy5 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 5 months ago by Denis-de-Bernardy (previous) (diff)

comment:21 Denis-de-Bernardy5 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 5 months ago by Denis-de-Bernardy (previous) (diff)

comment:22 Denis-de-Bernardy5 months ago

Another related plugin is: #17376.

comment:23 ircbot5 months ago

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

comment:24 Denis-de-Bernardy5 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-Bernardy5 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 CreativeInfusion5 months ago

Related: #23483 (for UPLOADS)

comment:27 danielbachhuber4 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

Note: See TracTickets for help on using tickets.