Fix sub-app permissions bug, add Comments app, support Site Editor

- Root-cause fix for "Sorry, you are not allowed to access this page" on
  Menu Creator/Activity Log/Role Editor: remove_submenu_page() was
  corrupting WP core's user_can_access_admin_page() capability lookup.
  Sub-apps now stay registered in $submenu; MenuSerializer filters them
  out of the sidebar instead.
- Add a 6th sub-app, Comments, with a redirect from native edit-comments.php.
- Extend the window-chrome/taskbar framing to the Site Editor
  (site-editor.php), including a fix for a CSS position:fixed
  over-constraint bug that let its frame run past the viewport.
- Rewrite the taskbar from a single sessionStorage slot to a list so
  multiple minimized windows are each independently restorable.
- Extend native-dark.css coverage to the block editor's own chrome.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
nixpanel
2026-07-03 18:48:25 -05:00
co-authored by Claude Sonnet 5
parent b0b0a9999a
commit 8153d4397c
16 changed files with 1510 additions and 194 deletions
+57 -15
View File
@@ -6,15 +6,28 @@ use AuroraAdmin\Utility\Assets;
defined("ABSPATH") || exit();
/**
* Registers Aurora's 5 secondary full-page apps (Menu Creator, Admin
* Notices, Role Editor, Activity Log, Database Explorer). Each is a real WP
* admin page (proper capability check, working URL, its own hook_suffix for
* asset gating) registered as a submenu of "aurora-admin" — then
* immediately hidden from WordPress's own submenu via remove_submenu_page(),
* the standard register-but-hide trick. This keeps them out of the
* WP-native menu list (MenuSerializer never sees them, nothing to filter)
* while still being reachable, permission-checked pages; they're presented
* instead in the sidebar's dedicated Aurora nav section (see Shell::aurora_nav()).
* Registers Aurora's secondary full-page apps (Menu Creator, Admin Notices,
* Role Editor, Activity Log, Database Explorer, Plugins, Comments). Each is
* a real WP admin page (proper capability check, working URL, its own
* hook_suffix for asset gating) registered as a submenu of "aurora-admin"
* (or "plugins.php" for the Plugins page).
*
* These stay registered in WordPress's own $submenu — they are NOT hidden
* via remove_submenu_page(). An earlier version did call it (the standard
* "register but hide" trick), but that turned out to corrupt WP core's own
* access-control bookkeeping: user_can_access_admin_page() partly relies on
* $submenu still containing the entry to resolve the page's required
* capability, so removing it caused every user (including admins) to be
* denied with "Sorry, you are not allowed to access this page" — confirmed
* by reproducing the bug, disabling the remove_submenu_page() call, and
* watching it resolve immediately. Since Aurora already hides WordPress's
* entire native admin menu chrome (replaced by its own Vue sidebar), a
* still-registered-but-native-menu-invisible entry has no visible effect on
* its own — MenuSerializer::serialize() is what keeps these out of the
* sidebar's own WP-native-menu section (skips slugs prefixed
* "aurora-admin-", plus the "aurora-admin" top-level slug itself), so they
* aren't duplicated there. They're presented instead in the sidebar's
* dedicated Aurora nav section (see Shell::aurora_nav()).
*/
class SubApps
{
@@ -25,6 +38,7 @@ class SubApps
"aurora-admin-activity-log" => ["title" => "Activity Log", "entry" => "activity-log"],
"aurora-admin-database" => ["title" => "Database Explorer", "entry" => "database-explorer"],
"aurora-admin-plugins" => ["title" => "Installed Plugins", "entry" => "plugins"],
"aurora-admin-comments" => ["title" => "Comments", "entry" => "comments"],
];
private static $hook_suffixes = [];
@@ -32,19 +46,19 @@ class SubApps
public function __construct()
{
add_action("admin_menu", [self::class, "register_menus"]);
add_action("admin_menu", [self::class, "hide_from_native_submenu"], 999);
add_action("admin_enqueue_scripts", [self::class, "maybe_enqueue"]);
add_action("admin_init", [self::class, "redirect_native_pages"]);
}
public static function register_menus()
{
foreach (self::PAGES as $slug => $page) {
$parent = $slug === "aurora-admin-plugins" ? "plugins.php" : "aurora-admin";
$parent = self::parent_slug($slug);
$hook = add_submenu_page(
$parent,
__($page["title"], "aurora-admin"),
__($page["title"], "aurora-admin"),
$slug === "aurora-admin-plugins" ? "activate_plugins" : "manage_options",
self::capability($slug),
$slug,
[self::class, "render"]
);
@@ -52,11 +66,23 @@ class SubApps
}
}
public static function hide_from_native_submenu()
private static function parent_slug($slug)
{
foreach (array_keys(self::PAGES) as $slug) {
remove_submenu_page($slug === "aurora-admin-plugins" ? "plugins.php" : "aurora-admin", $slug);
if ($slug === "aurora-admin-plugins") {
return "plugins.php";
}
return "aurora-admin";
}
private static function capability($slug)
{
if ($slug === "aurora-admin-plugins") {
return "activate_plugins";
}
if ($slug === "aurora-admin-comments") {
return "edit_posts";
}
return "manage_options";
}
public static function maybe_enqueue($hook_suffix)
@@ -69,6 +95,22 @@ class SubApps
Assets::enqueue("aurora-admin-" . self::PAGES[$slug]["entry"], "entries/" . self::PAGES[$slug]["entry"] . ".js");
}
public static function redirect_native_pages()
{
global $pagenow;
if ($pagenow !== "edit-comments.php" || !current_user_can("edit_posts")) {
return;
}
if (isset($_GET["page"]) || wp_doing_ajax()) {
return;
}
wp_safe_redirect(admin_url("admin.php?page=aurora-admin-comments"));
exit;
}
public static function render()
{
$page = isset($_GET["page"]) ? sanitize_text_field(wp_unslash($_GET["page"])) : "";