Opened 4 weeks ago
Last modified 3 weeks ago
#9330 new defect (bug)
Fix `bp_is_site_home()` to ignore query strings
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | Activity | Keywords: | has-patch |
| Cc: |
Description
The Bug
bp_is_site_home() (introduced in 12.1.0) performs an exact string comparison of the full requested URL against home_url( '/' ):
function bp_is_site_home() {
$requested_url = bp_get_requested_url();
$home_url = home_url( '/' );
// ...
return $home_url === $requested_url;
}
bp_get_requested_url() includes the query string from $_SERVER['REQUEST_URI'], but home_url( '/' ) does not. This means any query parameter on the homepage URL causes bp_is_site_home() to return false:
https://example.com/→true✓https://example.com/?custom_param=value→false✗
Impact
This breaks component directory detection when a BuddyPress directory page is set as the WordPress static front page (page_on_front). Every component's parse_query() method relies on this check:
// From BP_Activity_Component::parse_query()
if ( bp_is_site_home() && bp_is_directory_homepage( $this->id ) ) {
$query->set( $this->rewrite_ids['directory'], 1 );
}
When bp_is_site_home() returns false, the directory flag is never set, so:
$bp->current_componentis never assigned$wp_query->queried_objectis never set to the directory pageis_buddypress()returnsfalse— BuddyPress template loading does not kick in- The theme falls through to WordPress's default page rendering, which displays empty content or a "page not found" for the BuddyPress directory page
This affects any plugin that adds query parameters to a BuddyPress directory homepage — not just custom parameters. For example, a plugin adding topic filtering (?bp-topic=slug), search refinement, or pagination parameters to the activity directory would trigger this when the activity page is the front page.
When the directory is NOT the front page (e.g., /activity/?param=value), this issue does not occur because WordPress's rewrite rules match the path and set the directory query var directly, bypassing the bp_is_site_home() check entirely.
Steps to Reproduce
- Set up BuddyPress with the Activity component enabled
- Go to Settings → Reading → set "Your homepage displays" to "A static page"
- Set "Homepage" to the Activity directory page
- Visit
https://example.com/— activity directory loads correctly ✓ - Visit
https://example.com/?anything=value— page not found / empty page ✗
Proposed Fix
Compare URL paths only, ignoring query strings. This matches how WordPress's own redirect_canonical() handles URL comparison (it strips query args before comparing):
function bp_is_site_home() {
$requested_url = bp_get_requested_url();
$home_url = home_url( '/' );
if ( is_customize_preview() && ! bp_is_email_customizer() ) {
$requested_url = wp_parse_url( $requested_url, PHP_URL_PATH );
$home_url = wp_parse_url( $home_url, PHP_URL_PATH );
}
// Compare paths only — query strings should not affect homepage detection.
$requested_path = wp_parse_url( $requested_url, PHP_URL_PATH );
$home_path = wp_parse_url( $home_url, PHP_URL_PATH );
return trailingslashit( (string) $requested_path ) === trailingslashit( (string) $home_path );
}
Scope
- 2 lines of functional code changed in one function in
bp-core-template.php - Zero behavioral change for URLs without query strings (the
trailingslashitpath comparison produces the same result as the current exact comparison for bare homepage URLs) - Fixes directory homepage detection for all components (Activity, Members, Groups, etc.) when query parameters are present
- The
is_customize_preview()branch already useswp_parse_url( ..., PHP_URL_PATH )— the fix extends this approach to the general case
Workaround
Plugins can work around this by filtering bp_get_requested_url to strip their custom query parameters:
add_filter( 'bp_get_requested_url', function ( $url ) {
if ( isset( $_GET['custom-param'] ) ) {
$url = remove_query_arg( 'custom-param', $url );
}
return $url;
}, 5 );
This is fragile because every plugin must independently strip its own parameters. The core fix is preferable.
I'm happy to submit a patch for this change.