Initial commit: Aurora Admin plugin
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace AuroraAdmin\Pages;
|
||||
|
||||
use AuroraAdmin\Utility\Assets;
|
||||
use AuroraAdmin\Options\Settings;
|
||||
|
||||
defined("ABSPATH") || exit();
|
||||
|
||||
class Dashboard
|
||||
{
|
||||
private static $hook_suffix = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
add_action("admin_menu", [self::class, "register_menu"]);
|
||||
// Runs late (after submenus are registered) to drop the duplicate
|
||||
// first submenu item WordPress auto-creates for a top-level menu.
|
||||
add_action("admin_menu", [self::class, "remove_duplicate_submenu"], 100);
|
||||
add_action("admin_enqueue_scripts", [self::class, "maybe_enqueue"]);
|
||||
}
|
||||
|
||||
public static function register_menu()
|
||||
{
|
||||
self::$hook_suffix = add_menu_page(
|
||||
__("Aurora Admin", "aurora-admin"),
|
||||
__("Aurora Admin", "aurora-admin"),
|
||||
"read",
|
||||
"aurora-admin",
|
||||
[self::class, "render"],
|
||||
"dashicons-admin-generic",
|
||||
3
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* WordPress auto-adds a submenu item duplicating the top-level menu
|
||||
* (same "Aurora Admin" label + slug). Remove it so the submenu only
|
||||
* shows the real child pages (e.g. Settings).
|
||||
*/
|
||||
public static function remove_duplicate_submenu()
|
||||
{
|
||||
remove_submenu_page("aurora-admin", "aurora-admin");
|
||||
}
|
||||
|
||||
public static function maybe_enqueue($hook_suffix)
|
||||
{
|
||||
if ($hook_suffix !== self::$hook_suffix) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assets::enqueue("aurora-admin-dashboard", "entries/dashboard.js");
|
||||
}
|
||||
|
||||
public static function render()
|
||||
{
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
$data = [
|
||||
"restUrl" => esc_url_raw(get_rest_url()),
|
||||
"restNonce" => wp_create_nonce("wp_rest"),
|
||||
"userName" => $current_user->display_name,
|
||||
"settings" => Settings::get(),
|
||||
];
|
||||
?>
|
||||
<div
|
||||
id="aurora-admin-dashboard-root"
|
||||
data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>"
|
||||
></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
namespace AuroraAdmin\Pages;
|
||||
|
||||
use AuroraAdmin\Utility\Assets;
|
||||
use AuroraAdmin\Options\Settings;
|
||||
|
||||
defined("ABSPATH") || exit();
|
||||
|
||||
/**
|
||||
* Replaces the native WordPress dashboard (index.php) with Aurora's own
|
||||
* dashboard, the way the original plugin did.
|
||||
*
|
||||
* Rather than removing/moving WordPress's dashboard DOM, we render the
|
||||
* Aurora mount point at the very top of the content area (the
|
||||
* `in_admin_header` hook fires there, before the native .wrap) and simply
|
||||
* hide the native dashboard's .wrap with CSS. Clean and reversible — if
|
||||
* this plugin is disabled, the native dashboard returns untouched.
|
||||
*/
|
||||
class DashboardTakeover
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
add_action("admin_enqueue_scripts", [self::class, "maybe_enqueue"]);
|
||||
add_action("admin_head", [self::class, "hide_native"]);
|
||||
add_action("in_admin_header", [self::class, "render_mount"]);
|
||||
}
|
||||
|
||||
public static function is_dashboard()
|
||||
{
|
||||
return isset($GLOBALS["pagenow"]) && $GLOBALS["pagenow"] === "index.php";
|
||||
}
|
||||
|
||||
public static function maybe_enqueue()
|
||||
{
|
||||
if (!self::is_dashboard()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assets::enqueue("aurora-admin-dashboard", "entries/dashboard.js");
|
||||
}
|
||||
|
||||
public static function hide_native()
|
||||
{
|
||||
if (!self::is_dashboard()) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<style id="aurora-admin-dashboard-takeover">
|
||||
/* The Aurora dashboard is rendered in #wpcontent (above #wpbody) via
|
||||
in_admin_header, so the entire native #wpbody — heading, welcome
|
||||
panel, widgets, and the Screen Options / Help tabs inside it — is
|
||||
hidden. This leaves just the Aurora dashboard with no empty native
|
||||
frame below it. Printed only on the dashboard screen. */
|
||||
html.aurora-active #wpbody {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function render_mount()
|
||||
{
|
||||
if (!self::is_dashboard()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
$data = [
|
||||
"restUrl" => esc_url_raw(get_rest_url()),
|
||||
"restNonce" => wp_create_nonce("wp_rest"),
|
||||
"userName" => $current_user->display_name,
|
||||
"settings" => Settings::get_safe(),
|
||||
];
|
||||
?>
|
||||
<div
|
||||
id="aurora-admin-dashboard-root"
|
||||
data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>"
|
||||
></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
namespace AuroraAdmin\Pages;
|
||||
|
||||
use AuroraAdmin\Utility\Assets;
|
||||
use AuroraAdmin\Options\Settings;
|
||||
|
||||
defined("ABSPATH") || exit();
|
||||
|
||||
class SettingsPage
|
||||
{
|
||||
private static $hook_suffix = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
add_action("admin_menu", [self::class, "register_menu"]);
|
||||
add_action("admin_enqueue_scripts", [self::class, "maybe_enqueue"]);
|
||||
}
|
||||
|
||||
public static function register_menu()
|
||||
{
|
||||
// Top-level "Aurora Admin" menu opens the Settings page directly. The
|
||||
// Aurora dashboard is reached through WordPress's own Dashboard menu
|
||||
// (taken over on index.php), so this menu has no submenu of its own.
|
||||
self::$hook_suffix = add_menu_page(
|
||||
__("Aurora Admin", "aurora-admin"),
|
||||
__("Aurora Admin", "aurora-admin"),
|
||||
"manage_options",
|
||||
"aurora-admin",
|
||||
[self::class, "render"],
|
||||
"dashicons-admin-generic",
|
||||
3
|
||||
);
|
||||
}
|
||||
|
||||
public static function maybe_enqueue($hook_suffix)
|
||||
{
|
||||
if ($hook_suffix !== self::$hook_suffix) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assets::enqueue("aurora-admin-settings", "entries/settings.js");
|
||||
}
|
||||
|
||||
public static function render()
|
||||
{
|
||||
// Option lists for multiselect fields (roles for "Disable theme",
|
||||
// public post types for "Search post types").
|
||||
$roles = [];
|
||||
foreach (wp_roles()->roles as $slug => $info) {
|
||||
$roles[] = ["value" => $slug, "label" => translate_user_role($info["name"])];
|
||||
}
|
||||
|
||||
$post_types = [];
|
||||
foreach (get_post_types(["public" => true], "objects") as $pt) {
|
||||
if ($pt->name === "attachment") {
|
||||
continue;
|
||||
}
|
||||
$post_types[] = ["value" => $pt->name, "label" => $pt->labels->name];
|
||||
}
|
||||
|
||||
$data = [
|
||||
"restUrl" => esc_url_raw(get_rest_url()),
|
||||
"restNonce" => wp_create_nonce("wp_rest"),
|
||||
"userName" => wp_get_current_user()->display_name,
|
||||
// Full settings (including secrets) — this page is manage_options-only
|
||||
// and needs to display/edit them.
|
||||
"settings" => Settings::get(),
|
||||
"roles" => $roles,
|
||||
"postTypes" => $post_types,
|
||||
];
|
||||
?>
|
||||
<div
|
||||
id="aurora-admin-settings-root"
|
||||
data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>"
|
||||
></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
namespace AuroraAdmin\Pages;
|
||||
|
||||
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()).
|
||||
*/
|
||||
class SubApps
|
||||
{
|
||||
const PAGES = [
|
||||
"aurora-admin-menu-creator" => ["title" => "Menu Creator", "entry" => "menu-creator"],
|
||||
"aurora-admin-notices" => ["title" => "Admin Notices", "entry" => "admin-notices"],
|
||||
"aurora-admin-roles" => ["title" => "Role Editor", "entry" => "role-editor"],
|
||||
"aurora-admin-activity-log" => ["title" => "Activity Log", "entry" => "activity-log"],
|
||||
"aurora-admin-database" => ["title" => "Database Explorer", "entry" => "database-explorer"],
|
||||
];
|
||||
|
||||
private static $hook_suffixes = [];
|
||||
|
||||
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"]);
|
||||
}
|
||||
|
||||
public static function register_menus()
|
||||
{
|
||||
foreach (self::PAGES as $slug => $page) {
|
||||
$hook = add_submenu_page(
|
||||
"aurora-admin",
|
||||
__($page["title"], "aurora-admin"),
|
||||
__($page["title"], "aurora-admin"),
|
||||
"manage_options",
|
||||
$slug,
|
||||
[self::class, "render"]
|
||||
);
|
||||
self::$hook_suffixes[$slug] = $hook;
|
||||
}
|
||||
}
|
||||
|
||||
public static function hide_from_native_submenu()
|
||||
{
|
||||
foreach (array_keys(self::PAGES) as $slug) {
|
||||
remove_submenu_page("aurora-admin", $slug);
|
||||
}
|
||||
}
|
||||
|
||||
public static function maybe_enqueue($hook_suffix)
|
||||
{
|
||||
$slug = array_search($hook_suffix, self::$hook_suffixes, true);
|
||||
if ($slug === false || !isset(self::PAGES[$slug])) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assets::enqueue("aurora-admin-" . self::PAGES[$slug]["entry"], "entries/" . self::PAGES[$slug]["entry"] . ".js");
|
||||
}
|
||||
|
||||
public static function render()
|
||||
{
|
||||
$page = isset($_GET["page"]) ? sanitize_text_field(wp_unslash($_GET["page"])) : "";
|
||||
if (!isset(self::PAGES[$page])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$roles = [];
|
||||
foreach (wp_roles()->roles as $slug => $info) {
|
||||
$roles[] = ["value" => $slug, "label" => translate_user_role($info["name"])];
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$data = [
|
||||
"restUrl" => esc_url_raw(get_rest_url()),
|
||||
"restNonce" => wp_create_nonce("wp_rest"),
|
||||
"userName" => wp_get_current_user()->display_name,
|
||||
"roles" => $roles,
|
||||
"tablePrefix" => $wpdb->prefix,
|
||||
];
|
||||
$root_id = "aurora-admin-" . self::PAGES[$page]["entry"] . "-root";
|
||||
?>
|
||||
<div
|
||||
id="<?php echo esc_attr($root_id); ?>"
|
||||
data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>"
|
||||
></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user