Skip to content

Commit 458bc0c

Browse files
authored
fix(assets): enqueue wu-admin styles on addon pages for wu-form modals (#891)
PR #433 scoped admin asset enqueues to pages whose hook suffix contains `wp-ultimo`. Addon pages (e.g. multinetwork's `wu-networks`) have hook suffixes like `toplevel_page_wu-networks-network` that do not contain `wp-ultimo`, so wu-admin.css and wu-styling.css were never loaded. When those pages opened a wu-form modal (injected inline by wubox), the modal rendered with no styling. Changes: - Broaden wu_is_wu_page() to also match `_page_wu-`, covering both `toplevel_page_wu-*` and `{parent}_page_wu-*` slugs. The trailing hyphen avoids false positives on slugs like `wunderground`. - Add a new `wu_is_wu_page` filter so addons with non-standard slugs can explicitly opt in (or opt out). - Update PHPDoc with recognized patterns and filter usage example. - Add tests covering core, addon, false-positive, and filter cases. - Fix stale Scripts_Test.php assertions still referencing admin_init after the hook was moved to admin_enqueue_scripts in PR #433.
1 parent e0e89ae commit 458bc0c

3 files changed

Lines changed: 152 additions & 12 deletions

File tree

inc/functions/assets.php

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,33 @@ function wu_get_asset($asset, $assets_dir = 'img', $base_dir = 'assets') {
2929
}
3030

3131
/**
32-
* Checks if the current admin page belongs to WP Ultimo.
32+
* Checks if the current admin page belongs to Ultimate Multisite.
3333
*
34-
* Used to guard asset enqueues so that WP Ultimo scripts and styles are only
35-
* loaded on WP Ultimo admin pages, not on every page in the network admin.
34+
* Used to guard asset enqueues so that Ultimate Multisite scripts and styles are
35+
* only loaded on Ultimate Multisite admin pages, not on every page in the network
36+
* admin.
3637
*
37-
* Detection relies on the hook suffix passed to `admin_enqueue_scripts`. All
38-
* WP Ultimo admin pages register with an ID prefixed by `wp-ultimo`, which
39-
* WordPress uses when generating the page hook (e.g., `toplevel_page_wp-ultimo`,
40-
* `wp-ultimo_page_wp-ultimo-settings`). The hook suffix always contains the
41-
* page slug, so checking for `wp-ultimo` is reliable.
38+
* Detection relies on the hook suffix passed to `admin_enqueue_scripts`. Core
39+
* Ultimate Multisite admin pages register with an ID prefixed by `wp-ultimo`,
40+
* which WordPress embeds in the generated page hook (e.g.,
41+
* `toplevel_page_wp-ultimo`, `wp-ultimo_page_wp-ultimo-settings`). Addon pages
42+
* typically register with an ID prefixed by `wu-` (e.g., `wu-networks`,
43+
* `wu-sites-by-user`), and may appear either as top-level pages
44+
* (`toplevel_page_wu-foo`) or as submenus of other menus (`*_page_wu-foo`).
45+
*
46+
* Recognized patterns:
47+
* - Hook suffix contains `wp-ultimo` — core plugin pages and submenus.
48+
* - Hook suffix contains `_page_wu-` — any page with a slug starting `wu-`
49+
* (covers `toplevel_page_wu-*` and `{parent}_page_wu-*`).
50+
*
51+
* The result is passed through the `wu_is_wu_page` filter so addons can
52+
* explicitly register their pages when they use a non-standard slug.
4253
*
4354
* @since 2.4.2
55+
* @since 2.6.3 Recognize pages with `wu-` slug prefix and add `wu_is_wu_page` filter.
4456
*
4557
* @param string $hook_suffix The hook suffix passed to `admin_enqueue_scripts`.
46-
* @return bool True if the current page is a WP Ultimo admin page.
58+
* @return bool True if the current page is an Ultimate Multisite admin page.
4759
*/
4860
function wu_is_wu_page(string $hook_suffix = ''): bool {
4961

@@ -52,5 +64,30 @@ function wu_is_wu_page(string $hook_suffix = ''): bool {
5264
$hook_suffix = $screen ? (string) $screen->id : '';
5365
}
5466

55-
return str_contains($hook_suffix, 'wp-ultimo');
67+
$is_wu_page = str_contains($hook_suffix, 'wp-ultimo')
68+
|| str_contains($hook_suffix, '_page_wu-');
69+
70+
/**
71+
* Filters whether the current admin page is considered an Ultimate Multisite page.
72+
*
73+
* Addons that register admin pages with non-standard slugs (i.e., slugs that
74+
* do not contain `wp-ultimo` and do not start with `wu-`) should hook into
75+
* this filter to ensure the default Ultimate Multisite admin styles and
76+
* scripts (including wu-form modal styling) are enqueued on their pages.
77+
*
78+
* Example:
79+
*
80+
* add_filter( 'wu_is_wu_page', function ( $is_wu_page, $hook_suffix ) {
81+
* if ( str_contains( $hook_suffix, 'my-addon-slug' ) ) {
82+
* return true;
83+
* }
84+
* return $is_wu_page;
85+
* }, 10, 2 );
86+
*
87+
* @since 2.6.3
88+
*
89+
* @param bool $is_wu_page Whether the page is recognized as an Ultimate Multisite page.
90+
* @param string $hook_suffix The hook suffix for the current admin page.
91+
*/
92+
return (bool) apply_filters('wu_is_wu_page', $is_wu_page, $hook_suffix);
5693
}

tests/WP_Ultimo/Functions/Assets_Functions_Test.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,107 @@ public function test_wu_get_asset_custom_base_dir(): void {
6767

6868
$this->assertStringContainsString('static/img/', $result);
6969
}
70+
71+
/**
72+
* Core top-level page hook.
73+
*/
74+
public function test_wu_is_wu_page_matches_core_toplevel(): void {
75+
76+
$this->assertTrue(wu_is_wu_page('toplevel_page_wp-ultimo'));
77+
}
78+
79+
/**
80+
* Core submenu page hook.
81+
*/
82+
public function test_wu_is_wu_page_matches_core_submenu(): void {
83+
84+
$this->assertTrue(wu_is_wu_page('wp-ultimo_page_wp-ultimo-settings'));
85+
}
86+
87+
/**
88+
* Addon page with wu- slug prefix registered as top-level (regression for #706).
89+
*
90+
* When the multinetwork addon adds its `wu-networks` page at top level,
91+
* the hook suffix does not contain `wp-ultimo`. It must still be recognized
92+
* so wu-admin.css / wu-admin.js are enqueued, otherwise wu-form modals
93+
* on that page render un-styled.
94+
*/
95+
public function test_wu_is_wu_page_matches_addon_toplevel_wu_slug(): void {
96+
97+
$this->assertTrue(wu_is_wu_page('toplevel_page_wu-networks'));
98+
}
99+
100+
/**
101+
* Addon page with wu- slug prefix registered as network admin submenu.
102+
*/
103+
public function test_wu_is_wu_page_matches_addon_network_wu_slug(): void {
104+
105+
$this->assertTrue(wu_is_wu_page('toplevel_page_wu-networks-network'));
106+
}
107+
108+
/**
109+
* Addon page submenu of a non-wu parent with wu- slug.
110+
*/
111+
public function test_wu_is_wu_page_matches_addon_submenu_wu_slug(): void {
112+
113+
$this->assertTrue(wu_is_wu_page('settings_page_wu-custom-addon'));
114+
}
115+
116+
/**
117+
* Unrelated WordPress pages must not match.
118+
*/
119+
public function test_wu_is_wu_page_rejects_unrelated_pages(): void {
120+
121+
$this->assertFalse(wu_is_wu_page('edit-post'));
122+
$this->assertFalse(wu_is_wu_page('options-general'));
123+
$this->assertFalse(wu_is_wu_page('plugins'));
124+
$this->assertFalse(wu_is_wu_page('toplevel_page_other-plugin'));
125+
}
126+
127+
/**
128+
* A page slug that merely starts with `wu` (no hyphen) must not match, to
129+
* avoid false positives on slugs like `wunderground`.
130+
*/
131+
public function test_wu_is_wu_page_requires_hyphen_after_wu(): void {
132+
133+
$this->assertFalse(wu_is_wu_page('toplevel_page_wunderground'));
134+
}
135+
136+
/**
137+
* The wu_is_wu_page filter allows addons with non-standard slugs to opt in.
138+
*/
139+
public function test_wu_is_wu_page_filter_opt_in(): void {
140+
141+
$callback = function ($is_wu_page, $hook_suffix) {
142+
if ('toplevel_page_my-custom-addon' === $hook_suffix) {
143+
return true;
144+
}
145+
return $is_wu_page;
146+
};
147+
148+
add_filter('wu_is_wu_page', $callback, 10, 2);
149+
150+
$this->assertTrue(wu_is_wu_page('toplevel_page_my-custom-addon'));
151+
152+
remove_filter('wu_is_wu_page', $callback, 10);
153+
}
154+
155+
/**
156+
* The wu_is_wu_page filter allows opting out of a core match.
157+
*/
158+
public function test_wu_is_wu_page_filter_opt_out(): void {
159+
160+
$callback = function ($is_wu_page, $hook_suffix) {
161+
if ('toplevel_page_wp-ultimo' === $hook_suffix) {
162+
return false;
163+
}
164+
return $is_wu_page;
165+
};
166+
167+
add_filter('wu_is_wu_page', $callback, 10, 2);
168+
169+
$this->assertFalse(wu_is_wu_page('toplevel_page_wp-ultimo'));
170+
171+
remove_filter('wu_is_wu_page', $callback, 10);
172+
}
70173
}

tests/WP_Ultimo/Scripts_Test.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ public function test_init_registers_hooks(): void {
250250

251251
$this->assertNotFalse(has_action('init', [$this->scripts, 'register_default_scripts']));
252252
$this->assertNotFalse(has_action('init', [$this->scripts, 'register_default_styles']));
253-
$this->assertNotFalse(has_action('admin_init', [$this->scripts, 'enqueue_default_admin_styles']));
254-
$this->assertNotFalse(has_action('admin_init', [$this->scripts, 'enqueue_default_admin_scripts']));
253+
$this->assertNotFalse(has_action('admin_enqueue_scripts', [$this->scripts, 'enqueue_default_admin_styles']));
254+
$this->assertNotFalse(has_action('admin_enqueue_scripts', [$this->scripts, 'enqueue_default_admin_scripts']));
255255
$this->assertNotFalse(has_filter('admin_body_class', [$this->scripts, 'add_body_class_container_boxed']));
256256
}
257257

0 commit comments

Comments
 (0)