Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions inc/class-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,17 @@ public function default_sections(): void {
]
);

$this->add_field(
'sites',
'optimize_frontend_my_sites_toolbar',
[
'title' => __('Optimize the front-end My Sites toolbar', 'ultimate-multisite'),
'desc' => __('Show only the current site in the front-end toolbar to reduce processing on large networks. The complete site list remains available from the My Sites administration page.', 'ultimate-multisite'),
'type' => 'toggle',
'default' => 0,
]
);

$this->add_field(
'sites',
'wordpress_features_heading',
Expand Down Expand Up @@ -2177,6 +2188,7 @@ public static function get_setting_defaults(): array {
// Sites
'enable_visits_limiting' => 1,
'enable_screenshot_generator' => 1,
'optimize_frontend_my_sites_toolbar' => 0,
'menu_items_plugin' => 1,
'add_new_users' => 1,
'allow_template_switching' => 1,
Expand Down
74 changes: 74 additions & 0 deletions inc/managers/class-site-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,12 @@ public function hide_customer_sites_from_super_admin_list($sites, $user_id, $all
return $sites;
}

if ($this->is_frontend_my_sites_toolbar_request()) {
$sites = $this->get_current_site_for_frontend_my_sites_toolbar();

return apply_filters('get_blogs_of_user', $sites, $user_id, $all); // phpcs:ignore
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

$keys = get_user_meta($user_id);

if (empty($keys)) {
Expand Down Expand Up @@ -1271,6 +1277,74 @@ public function hide_customer_sites_from_super_admin_list($sites, $user_id, $all
return apply_filters('get_blogs_of_user', $sites, $user_id, $all); // phpcs:ignore
}

/**
* Determines whether get_blogs_of_user is preparing the front-end My Sites toolbar.
*
* The pre_get_blogs_of_user filter is also used by wp-admin, REST requests, and
* application code. Checking the WP_Admin_Bar initialization call keeps the
* optimization limited to the nested toolbar request instead of limiting every
* front-end get_blogs_of_user() call.
*
* @since 2.15.0
* @param array|null $backtrace Call stack override used by tests.
* @return bool
*/
protected function is_frontend_my_sites_toolbar_request($backtrace = null) {

if (
! wu_get_setting('optimize_frontend_my_sites_toolbar', false)
|| is_admin()
|| wp_doing_ajax()
|| wp_doing_cron()
|| (defined('REST_REQUEST') && REST_REQUEST)
|| (defined('WP_CLI') && WP_CLI)
|| ! is_user_logged_in()
|| ! is_admin_bar_showing()
) {
return false;
}

$backtrace = $backtrace ?? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 12); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace

foreach ($backtrace as $call) {
if ('WP_Admin_Bar' === ($call['class'] ?? '') && 'initialize' === ($call['function'] ?? '')) {
return true;
}
}

return false;
}

/**
* Returns the current site in the format expected by the My Sites toolbar.
*
* @since 2.15.0
* @return object[]
*/
protected function get_current_site_for_frontend_my_sites_toolbar() {

$site = get_site(get_current_blog_id());

if ( ! $site) {
return [];
}

return [
$site->id => (object) [
'userblog_id' => $site->id,
'blogname' => $site->blogname,
'domain' => $site->domain,
'path' => $site->path,
'site_id' => $site->network_id,
'siteurl' => $site->siteurl,
'archived' => $site->archived,
'mature' => $site->mature,
'spam' => $site->spam,
'deleted' => $site->deleted,
],
];
}

/**
* Delete pending sites from non-pending memberships
*
Expand Down
117 changes: 117 additions & 0 deletions tests/WP_Ultimo/Managers/Site_Manager_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@

use WP_Ultimo\Managers\Site_Manager;

// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
class Frontend_My_Sites_Toolbar_Test_Manager extends Site_Manager {

protected function is_frontend_my_sites_toolbar_request($backtrace = null) {

return true;
}
}
// phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound

// phpcs:ignore Generic.Files.OneObjectStructurePerFile.MultipleFound
class Site_Manager_Test extends \WP_UnitTestCase {

use Manager_Test_Trait;
Expand Down Expand Up @@ -511,7 +522,7 @@

wu_save_setting('search_and_replace', []);

add_filter('wu_search_and_replace_on_duplication', function ($settings, $from, $to) {

Check warning on line 525 in tests/WP_Ultimo/Managers/Site_Manager_Test.php

View workflow job for this annotation

GitHub Actions / Code Quality Checks

The method parameter $to is never used

Check warning on line 525 in tests/WP_Ultimo/Managers/Site_Manager_Test.php

View workflow job for this annotation

GitHub Actions / Code Quality Checks

The method parameter $from is never used
$settings['filter-key'] = 'filter-value';
return $settings;
}, 10, 3);
Expand Down Expand Up @@ -2943,7 +2954,7 @@

$filter_applied = false;

add_filter('get_blogs_of_user', function ($sites, $uid, $all) use (&$filter_applied) {

Check warning on line 2957 in tests/WP_Ultimo/Managers/Site_Manager_Test.php

View workflow job for this annotation

GitHub Actions / Code Quality Checks

The method parameter $all is never used

Check warning on line 2957 in tests/WP_Ultimo/Managers/Site_Manager_Test.php

View workflow job for this annotation

GitHub Actions / Code Quality Checks

The method parameter $uid is never used
$filter_applied = true;
return $sites;
}, 10, 3);
Expand All @@ -2958,6 +2969,112 @@
wp_set_current_user(0);
}

/**
* Test the front-end My Sites toolbar optimization applies get_blogs_of_user filter.
*/
public function test_frontend_my_sites_toolbar_optimization_applies_get_blogs_of_user_filter(): void {

$reflection = new \ReflectionClass(Frontend_My_Sites_Toolbar_Test_Manager::class);
$manager = $reflection->newInstanceWithoutConstructor();
$user_id = $this->factory()->user->create(['role' => 'administrator']);
$filter = function ($sites, $filter_user_id, $all) {

unset($all);
$sites['filtered'] = (object) ['userblog_id' => $filter_user_id];

return $sites;
};

grant_super_admin($user_id);
wp_set_current_user($user_id);
add_filter('get_blogs_of_user', $filter, 10, 3);

try {
$sites = $manager->hide_customer_sites_from_super_admin_list([], $user_id, false);

$this->assertArrayHasKey('filtered', $sites);
$this->assertSame($user_id, $sites['filtered']->userblog_id);
} finally {
remove_filter('get_blogs_of_user', $filter, 10);
revoke_super_admin($user_id);
wp_set_current_user(0);
}
}

/**
* Test front-end My Sites toolbar optimization requires the admin bar call stack.
*/
public function test_frontend_my_sites_toolbar_optimization_requires_admin_bar_initialization(): void {

$manager = $this->get_manager_instance();
$user_id = $this->factory()->user->create(['role' => 'administrator']);
$method = new \ReflectionMethod(Site_Manager::class, 'is_frontend_my_sites_toolbar_request');
$filter = function ($value, $setting) {
return 'optimize_frontend_my_sites_toolbar' === $setting ? 1 : $value;
};

wp_set_current_user($user_id);
add_filter('wu_get_setting', $filter, 10, 2);
add_filter('show_admin_bar', '__return_true');

try {
$this->assertTrue(
$method->invoke($manager, [
[
'class' => 'WP_Admin_Bar',
'function' => 'initialize',
],
])
);
$this->assertFalse($method->invoke($manager, []));
} finally {
remove_filter('wu_get_setting', $filter, 10);
remove_filter('show_admin_bar', '__return_true');
wp_set_current_user(0);
}
}

/**
* Test front-end My Sites toolbar optimization remains disabled by default.
*/
public function test_frontend_my_sites_toolbar_optimization_is_disabled_by_default(): void {

$manager = $this->get_manager_instance();
$user_id = $this->factory()->user->create(['role' => 'administrator']);
$method = new \ReflectionMethod(Site_Manager::class, 'is_frontend_my_sites_toolbar_request');

wp_set_current_user($user_id);
add_filter('show_admin_bar', '__return_true');

try {
$this->assertFalse(
$method->invoke($manager, [
[
'class' => 'WP_Admin_Bar',
'function' => 'initialize',
],
])
);
} finally {
remove_filter('show_admin_bar', '__return_true');
wp_set_current_user(0);
}
}

/**
* Test the toolbar optimization supplies only the active site.
*/
public function test_frontend_my_sites_toolbar_optimization_returns_current_site_only(): void {

$manager = $this->get_manager_instance();
$method = new \ReflectionMethod(Site_Manager::class, 'get_current_site_for_frontend_my_sites_toolbar');
$sites = $method->invoke($manager);

$this->assertCount(1, $sites);
$this->assertArrayHasKey(get_current_blog_id(), $sites);
$this->assertSame(get_current_blog_id(), $sites[ get_current_blog_id() ]->userblog_id);
}

// ========================================================================
// init – demo-related hooks
// ========================================================================
Expand Down Expand Up @@ -3547,7 +3664,7 @@
wu_save_setting('network_logo', 'https://example.com/logo.png');

// Register the 'login' style so wp_add_inline_style doesn't fail.
wp_register_style('login', false);

Check warning on line 3667 in tests/WP_Ultimo/Managers/Site_Manager_Test.php

View workflow job for this annotation

GitHub Actions / Code Quality Checks

Resource version not set in call to wp_register_style(). This means new versions of the style may not always be loaded due to browser caching.

$manager = $this->get_manager_instance();

Expand Down Expand Up @@ -3798,7 +3915,7 @@

$filter_applied = false;

add_filter('wu_demo_go_live_url', function ($url, $site) use (&$filter_applied) {

Check warning on line 3918 in tests/WP_Ultimo/Managers/Site_Manager_Test.php

View workflow job for this annotation

GitHub Actions / Code Quality Checks

The method parameter $site is never used
$filter_applied = true;
return $url;
}, 10, 2);
Expand Down
15 changes: 15 additions & 0 deletions tests/WP_Ultimo/Settings_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,21 @@ public function test_get_setting_defaults_disables_passwordless_login() {
$this->assertSame(0, $defaults['use_passwordless_login']);
}

public function test_get_setting_defaults_disables_frontend_my_sites_toolbar_optimization() {
$defaults = Settings::get_setting_defaults();
$this->assertArrayHasKey('optimize_frontend_my_sites_toolbar', $defaults);
$this->assertSame(0, $defaults['optimize_frontend_my_sites_toolbar']);
}

public function test_sites_section_has_frontend_my_sites_toolbar_optimization_field() {
$section = $this->settings->get_section('sites');
$field = $section['fields']['optimize_frontend_my_sites_toolbar'];

$this->assertSame('toggle', $field['type']);
$this->assertSame(0, $field['default']);
$this->assertStringContainsString('My Sites administration page', $field['desc']);
}

// ------------------------------------------------------------------
// General section fields
// ------------------------------------------------------------------
Expand Down
Loading