Initial commit: Aurora Admin plugin
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
namespace AuroraAdmin\MenuCreator;
|
||||
|
||||
defined("ABSPATH") || exit();
|
||||
|
||||
/**
|
||||
* REST CRUD for saved menu configurations. GET/POST /menus,
|
||||
* GET/PUT/DELETE /menus/:id. All manage_options-gated.
|
||||
*/
|
||||
class MenuCreatorData
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
add_action("rest_api_init", [self::class, "register"]);
|
||||
}
|
||||
|
||||
public static function register()
|
||||
{
|
||||
$permission = function () {
|
||||
return current_user_can("manage_options");
|
||||
};
|
||||
|
||||
register_rest_route("aurora-admin/v1", "/menus", [
|
||||
[
|
||||
"methods" => "GET",
|
||||
"callback" => [self::class, "list_menus"],
|
||||
"permission_callback" => $permission,
|
||||
"args" => [
|
||||
"status" => ["type" => "string", "required" => false],
|
||||
],
|
||||
],
|
||||
[
|
||||
"methods" => "POST",
|
||||
"callback" => [self::class, "create"],
|
||||
"permission_callback" => $permission,
|
||||
"args" => [
|
||||
"name" => ["type" => "string", "required" => true],
|
||||
"status" => ["type" => "string", "required" => false],
|
||||
"roles" => ["type" => "array", "required" => false],
|
||||
"items" => ["type" => "array", "required" => false],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
register_rest_route("aurora-admin/v1", "/menus/native-items", [
|
||||
"methods" => "GET",
|
||||
"callback" => [self::class, "native_items"],
|
||||
"permission_callback" => $permission,
|
||||
]);
|
||||
|
||||
register_rest_route("aurora-admin/v1", "/menus/(?P<id>\d+)", [
|
||||
[
|
||||
"methods" => "GET",
|
||||
"callback" => [self::class, "get_one"],
|
||||
"permission_callback" => $permission,
|
||||
],
|
||||
[
|
||||
"methods" => "PUT",
|
||||
"callback" => [self::class, "update"],
|
||||
"permission_callback" => $permission,
|
||||
"args" => [
|
||||
"name" => ["type" => "string", "required" => false],
|
||||
"status" => ["type" => "string", "required" => false],
|
||||
"roles" => ["type" => "array", "required" => false],
|
||||
"items" => ["type" => "array", "required" => false],
|
||||
],
|
||||
],
|
||||
[
|
||||
"methods" => "DELETE",
|
||||
"callback" => [self::class, "delete"],
|
||||
"permission_callback" => $permission,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The real, current WordPress menu (same source MenuSerializer feeds to
|
||||
* the sidebar) flattened so the menu editor has something concrete to
|
||||
* toggle hide/rename on — top-level items plus their submenu items.
|
||||
*/
|
||||
public static function native_items()
|
||||
{
|
||||
$menu = \AuroraAdmin\Shell\MenuSerializer::serialize();
|
||||
$flat = [];
|
||||
foreach ($menu as $item) {
|
||||
if (!empty($item["separator"]) || empty($item["id"])) {
|
||||
continue;
|
||||
}
|
||||
$flat[] = ["native_id" => $item["id"], "title" => $item["title"], "icon" => $item["icon"]];
|
||||
foreach ($item["submenu"] ?? [] as $sub) {
|
||||
if (empty($sub["id"])) {
|
||||
continue;
|
||||
}
|
||||
$flat[] = ["native_id" => $sub["id"], "title" => $item["title"] . " › " . $sub["title"], "icon" => null];
|
||||
}
|
||||
}
|
||||
return new \WP_REST_Response($flat, 200);
|
||||
}
|
||||
|
||||
public static function list_menus($request)
|
||||
{
|
||||
global $wpdb;
|
||||
$table = MenuCreator::table_name();
|
||||
$status = $request->get_param("status");
|
||||
|
||||
if ($status) {
|
||||
$rows = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM {$table} WHERE status = %s ORDER BY updated_at DESC",
|
||||
$status
|
||||
));
|
||||
} else {
|
||||
$rows = $wpdb->get_results("SELECT * FROM {$table} ORDER BY updated_at DESC");
|
||||
}
|
||||
|
||||
return new \WP_REST_Response(array_map([self::class, "format"], $rows), 200);
|
||||
}
|
||||
|
||||
public static function get_one($request)
|
||||
{
|
||||
global $wpdb;
|
||||
$row = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM " . MenuCreator::table_name() . " WHERE id = %d",
|
||||
(int) $request->get_param("id")
|
||||
));
|
||||
if (!$row) {
|
||||
return new \WP_Error("not_found", "Menu not found", ["status" => 404]);
|
||||
}
|
||||
return new \WP_REST_Response(self::format($row), 200);
|
||||
}
|
||||
|
||||
public static function create($request)
|
||||
{
|
||||
global $wpdb;
|
||||
$now = current_time("mysql");
|
||||
|
||||
$wpdb->insert(MenuCreator::table_name(), [
|
||||
"name" => sanitize_text_field($request->get_param("name")),
|
||||
"status" => self::sanitize_status($request->get_param("status")),
|
||||
"roles" => wp_json_encode(self::sanitize_roles($request->get_param("roles"))),
|
||||
"items" => wp_json_encode(self::sanitize_items($request->get_param("items"))),
|
||||
"created_at" => $now,
|
||||
"updated_at" => $now,
|
||||
]);
|
||||
|
||||
return self::get_one(new \WP_REST_Request("GET", "", ["id" => $wpdb->insert_id]));
|
||||
}
|
||||
|
||||
public static function update($request)
|
||||
{
|
||||
global $wpdb;
|
||||
$id = (int) $request->get_param("id");
|
||||
$fields = ["updated_at" => current_time("mysql")];
|
||||
|
||||
if ($request->get_param("name") !== null) {
|
||||
$fields["name"] = sanitize_text_field($request->get_param("name"));
|
||||
}
|
||||
if ($request->get_param("status") !== null) {
|
||||
$fields["status"] = self::sanitize_status($request->get_param("status"));
|
||||
}
|
||||
if ($request->get_param("roles") !== null) {
|
||||
$fields["roles"] = wp_json_encode(self::sanitize_roles($request->get_param("roles")));
|
||||
}
|
||||
if ($request->get_param("items") !== null) {
|
||||
$fields["items"] = wp_json_encode(self::sanitize_items($request->get_param("items")));
|
||||
}
|
||||
|
||||
$wpdb->update(MenuCreator::table_name(), $fields, ["id" => $id]);
|
||||
|
||||
return self::get_one($request);
|
||||
}
|
||||
|
||||
public static function delete($request)
|
||||
{
|
||||
global $wpdb;
|
||||
$wpdb->delete(MenuCreator::table_name(), ["id" => (int) $request->get_param("id")]);
|
||||
return new \WP_REST_Response(["deleted" => true], 200);
|
||||
}
|
||||
|
||||
private static function format($row)
|
||||
{
|
||||
return [
|
||||
"id" => (int) $row->id,
|
||||
"name" => $row->name,
|
||||
"status" => $row->status,
|
||||
"roles" => json_decode($row->roles ?: "[]", true) ?: [],
|
||||
"items" => json_decode($row->items ?: "[]", true) ?: [],
|
||||
"createdAt" => $row->created_at,
|
||||
"updatedAt" => $row->updated_at,
|
||||
];
|
||||
}
|
||||
|
||||
private static function sanitize_status($status)
|
||||
{
|
||||
return $status === "published" ? "published" : "draft";
|
||||
}
|
||||
|
||||
private static function sanitize_roles($roles)
|
||||
{
|
||||
if (!is_array($roles)) {
|
||||
return [];
|
||||
}
|
||||
$valid = array_keys(wp_roles()->roles);
|
||||
return array_values(array_intersect(array_map("sanitize_key", $roles), $valid));
|
||||
}
|
||||
|
||||
private static function sanitize_items($items)
|
||||
{
|
||||
if (!is_array($items)) {
|
||||
return [];
|
||||
}
|
||||
$out = [];
|
||||
foreach ($items as $item) {
|
||||
if (!is_array($item) || empty($item["native_id"])) {
|
||||
continue;
|
||||
}
|
||||
$out[] = [
|
||||
"native_id" => sanitize_text_field($item["native_id"]),
|
||||
"label" => isset($item["label"]) ? sanitize_text_field($item["label"]) : "",
|
||||
"hidden" => !empty($item["hidden"]),
|
||||
"order" => isset($item["order"]) ? (int) $item["order"] : 0,
|
||||
];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user