Opened 2 years ago
Closed 6 months ago
#59522 closed defect (bug) (worksforme)
Bug handling multisites where main site URL and main blog URL are different
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Priority: | normal | |
| Severity: | normal | Version: | 6.3 |
| Component: | Networks and Sites | Keywords: | has-patch needs-testing |
| Focuses: | multisite | Cc: |
Description
WordPress 6.3 and up appear to break handling of multisites where the BLOG_ID_CURRENT_SITE and the domain and path for the network in the wp_site table do not point at the same blog. It treats the the site configured in wp_site as if it is also the main blog in the network (over-riding BLOG_ID_CURRENT_SITE). This results in image paths being broken on the site set in wp_site if it is not in the root directory.
How to recreate the bug:
- In WordPress 6.2 or below, create a directory-based multisite, with 2 sites in the network, site 1 at just
http://localhostand site 2 athttp://localhost/foo. Inwp-config.php, set bothSITE_ID_CURRENT_SITEandBLOG_ID_CURRENT_SITEto1. In thewp_sitetable (which should only contain 1 entry, with ID1), set the domain tolocalhostand the path to/foo/. - Upload an image to the media library of
http://localhost/foo. It should display correctly in the library, and have a URL ofhttp://localhost/onsblog/wp-content/uploads/sites/foo/[year]/[month]/[your-filename]. - In the network site list, at
http://localhost/foo/network/sites.php,localhostshould be marked as the main site, reflecting theBLOG_ID_CURRENT_SITEconstant. - Upgrade to WordPress 6.3 or 6.3.1.
- In the media library of
http://localhost/foo, the uploaded image will no longer display. If you view the image properties, it will report an image URL ofhttp://localhost/onsblog/wp-content/uploads/[year]/[month]/[your-filename], i.e. the subsite part of the path is missing. - In the network site list,
localhost/foois now marked as the main site, which does not reflect theBLOG_ID_CURRENT_SITEsetting.
This bug also results in all images uploaded via the classic editor prior to 6.3 404-ing in the frontend on the affected subsite post-upgrade.
This behaviour was introduced in this commit: https://github.com/WordPress/WordPress/commit/05f19b1ed76af6d60855a1d44b8c15a166c5e36f, presumably unintentionally given the commit message. This line specifically is the issue: https://github.com/WordPress/WordPress/commit/05f19b1ed76af6d60855a1d44b8c15a166c5e36f#diff-254cbb80547c44f4b3a7ef37746bb5eb9f42bf29f0de5215034a8d1015928fecR242.
When the WP_Network object is populated via the WP_Network::get_instance() method, the $id property is populated via a WPDB query: https://github.com/WordPress/WordPress/blob/master/wp-includes/class-wp-network.php#L106. This returns the id from the database as a string (normally '1'), which is then passed into WP_Network::__construct(), resulting in the id property being populated as a string. Therefore this check:
( defined( 'SITE_ID_CURRENT_SITE' ) && (int) SITE_ID_CURRENT_SITE === $this->id )
will always return false, as $this->id will be a string. Either $this->id should also be cast as an integer, or the WP_Network::__construct() method should perform type enforcement, e.g. by calling the same class's __set() method to set properties.
Change History (4)
This ticket was mentioned in PR #5369 on WordPress/wordpress-develop by RobjS.
2 years ago
#1
- Keywords has-patch added
Before: when the
WP_Networkobject was populated viaWP_Network::get_instance(), the WPDB query would returnidas a string, and the constructor would then set theidproperty as that string. However, elsewhere the class assumes theidwill always be an integer, and strictly typed comparisons (e.g. l.242) were therefore returning an unexpected result. This resulted in multi-sites where the network URL (set via thewp_sitetable) did not point to the same blog as theBLOG_ID_CURRENT_SITEbreaking in WordPress 6.3 and up.Now: the constructor uses the
__set()method to ensure that properties are always cast to the expected type.