Add a real replacement Posts management page (v2.5.0)
Posts was previously just dark-themed skinning over the native edit.php list table, unlike Comments/Plugins which are genuine replacements. Built the same way: new PostsData.php REST controller (list with status/search filters matching native tabs, trash, restore, permanent delete) and a Vue page matching the Comments layout. - SubApps.php registers it as aurora-admin-posts, parented under edit.php (same pattern as Plugins under plugins.php). - redirect_native_pages() redirects direct edit.php visits (typed URL, not just the sidebar link) to the Aurora page — gated to the default post type only, so Pages and other custom post types are untouched. - MenuSerializer rewrites the sidebar's Posts/All Posts links the same way Plugins/Comments already were. - Gated by Settings > Posts' "Modern posts table" toggle, re-added now that it has a real implementation (it was removed a few commits ago for describing a feature that didn't exist). - Fixed modern_plugins/modern_comments/modern_posts all defaulting to visually "on" in the Settings UI to match their actual PHP default. Verified live: trash/restore/status filters/search all work correctly, edit.php redirects to the Aurora page, edit.php?post_type=page (Pages) correctly does not. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d8bf1ae049
commit
56b6674527
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
namespace AuroraAdmin\Rest;
|
||||
|
||||
defined("ABSPATH") || exit();
|
||||
|
||||
/**
|
||||
* REST endpoints for Aurora's custom Posts page — a real replacement for
|
||||
* the native edit.php list table (unlike Settings > Posts' old "Modern
|
||||
* posts table" toggle, which described this but was never actually built;
|
||||
* that toggle was removed once this landed).
|
||||
*/
|
||||
class PostsData
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
add_action("rest_api_init", [self::class, "register"]);
|
||||
}
|
||||
|
||||
public static function register()
|
||||
{
|
||||
register_rest_route("aurora-admin/v1", "/posts", [
|
||||
"methods" => "GET",
|
||||
"callback" => [self::class, "list_posts"],
|
||||
"permission_callback" => function () {
|
||||
return current_user_can("edit_posts");
|
||||
},
|
||||
"args" => [
|
||||
"status" => ["type" => "string", "required" => false],
|
||||
"search" => ["type" => "string", "required" => false],
|
||||
"page" => ["type" => "integer", "required" => false],
|
||||
"perPage" => ["type" => "integer", "required" => false],
|
||||
],
|
||||
]);
|
||||
|
||||
register_rest_route("aurora-admin/v1", "/posts/trash", [
|
||||
"methods" => "POST",
|
||||
"callback" => [self::class, "trash_post"],
|
||||
"permission_callback" => [self::class, "can_edit_param_post"],
|
||||
"args" => [
|
||||
"id" => ["type" => "integer", "required" => true],
|
||||
],
|
||||
]);
|
||||
|
||||
register_rest_route("aurora-admin/v1", "/posts/restore", [
|
||||
"methods" => "POST",
|
||||
"callback" => [self::class, "restore_post"],
|
||||
"permission_callback" => [self::class, "can_edit_param_post"],
|
||||
"args" => [
|
||||
"id" => ["type" => "integer", "required" => true],
|
||||
],
|
||||
]);
|
||||
|
||||
register_rest_route("aurora-admin/v1", "/posts/(?P<id>\d+)", [
|
||||
"methods" => "DELETE",
|
||||
"callback" => [self::class, "delete_post"],
|
||||
"permission_callback" => [self::class, "can_delete_route_post"],
|
||||
"args" => [
|
||||
"id" => ["type" => "integer", "required" => true],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public static function can_edit_param_post($request)
|
||||
{
|
||||
$id = (int) $request->get_param("id");
|
||||
return $id && current_user_can("edit_post", $id);
|
||||
}
|
||||
|
||||
public static function can_delete_route_post($request)
|
||||
{
|
||||
$id = (int) $request["id"];
|
||||
return $id && current_user_can("delete_post", $id);
|
||||
}
|
||||
|
||||
public static function list_posts($request)
|
||||
{
|
||||
$status = self::query_status($request->get_param("status"));
|
||||
$page = max(1, (int) ($request->get_param("page") ?: 1));
|
||||
$per_page = min(100, max(10, (int) ($request->get_param("perPage") ?: 20)));
|
||||
$search = sanitize_text_field((string) $request->get_param("search"));
|
||||
|
||||
$args = [
|
||||
"post_type" => "post",
|
||||
"post_status" => $status,
|
||||
"posts_per_page" => $per_page,
|
||||
"paged" => $page,
|
||||
"orderby" => "date",
|
||||
"order" => "DESC",
|
||||
"ignore_sticky_posts" => true,
|
||||
];
|
||||
|
||||
if ($search !== "") {
|
||||
$args["s"] = $search;
|
||||
}
|
||||
|
||||
$query = new \WP_Query($args);
|
||||
|
||||
return new \WP_REST_Response([
|
||||
"items" => array_map([self::class, "serialize_post"], $query->posts),
|
||||
"stats" => self::stats(),
|
||||
"pagination" => [
|
||||
"page" => $page,
|
||||
"perPage" => $per_page,
|
||||
"total" => (int) $query->found_posts,
|
||||
"totalPages" => max(1, (int) $query->max_num_pages),
|
||||
],
|
||||
], 200);
|
||||
}
|
||||
|
||||
public static function trash_post($request)
|
||||
{
|
||||
$id = (int) $request->get_param("id");
|
||||
$post = get_post($id);
|
||||
if (!$post || $post->post_type !== "post") {
|
||||
return new \WP_Error("aurora_post_invalid", __("Invalid post.", "aurora-admin"), ["status" => 400]);
|
||||
}
|
||||
|
||||
$result = wp_trash_post($id);
|
||||
if (!$result) {
|
||||
return new \WP_Error("aurora_post_trash_failed", __("Could not trash the post.", "aurora-admin"), ["status" => 500]);
|
||||
}
|
||||
|
||||
return new \WP_REST_Response(["success" => true, "message" => __("Post moved to trash.", "aurora-admin")], 200);
|
||||
}
|
||||
|
||||
public static function restore_post($request)
|
||||
{
|
||||
$id = (int) $request->get_param("id");
|
||||
$post = get_post($id);
|
||||
if (!$post || $post->post_type !== "post") {
|
||||
return new \WP_Error("aurora_post_invalid", __("Invalid post.", "aurora-admin"), ["status" => 400]);
|
||||
}
|
||||
|
||||
$result = wp_untrash_post($id);
|
||||
if (!$result) {
|
||||
return new \WP_Error("aurora_post_restore_failed", __("Could not restore the post.", "aurora-admin"), ["status" => 500]);
|
||||
}
|
||||
|
||||
return new \WP_REST_Response(["success" => true, "message" => __("Post restored.", "aurora-admin")], 200);
|
||||
}
|
||||
|
||||
public static function delete_post($request)
|
||||
{
|
||||
$id = (int) $request["id"];
|
||||
$post = get_post($id);
|
||||
if (!$post || $post->post_type !== "post") {
|
||||
return new \WP_Error("aurora_post_invalid", __("Invalid post.", "aurora-admin"), ["status" => 400]);
|
||||
}
|
||||
|
||||
$result = wp_delete_post($id, true);
|
||||
if (!$result) {
|
||||
return new \WP_Error("aurora_post_delete_failed", __("Could not delete the post.", "aurora-admin"), ["status" => 500]);
|
||||
}
|
||||
|
||||
return new \WP_REST_Response(["success" => true, "message" => __("Post deleted.", "aurora-admin")], 200);
|
||||
}
|
||||
|
||||
private static function serialize_post($post)
|
||||
{
|
||||
$author = get_userdata($post->post_author);
|
||||
$categories = wp_get_post_categories($post->ID, ["fields" => "names"]);
|
||||
$status = $post->post_status;
|
||||
|
||||
return [
|
||||
"id" => (int) $post->ID,
|
||||
"title" => get_the_title($post) ?: __("(No title)", "aurora-admin"),
|
||||
"author" => $author ? $author->display_name : __("Unknown", "aurora-admin"),
|
||||
"categories" => is_array($categories) ? $categories : [],
|
||||
"commentCount" => (int) $post->comment_count,
|
||||
"date" => get_the_date("M j, Y", $post),
|
||||
"dateLabel" =>
|
||||
$status === "publish"
|
||||
? __("Published", "aurora-admin")
|
||||
: ($status === "future"
|
||||
? __("Scheduled", "aurora-admin")
|
||||
: __("Last Modified", "aurora-admin")),
|
||||
"status" => $status,
|
||||
"statusLabel" => self::status_label($status),
|
||||
"editUrl" => get_edit_post_link($post->ID, "raw") ?: "",
|
||||
"viewUrl" => $status === "publish" ? get_permalink($post) : get_preview_post_link($post),
|
||||
"canDelete" => current_user_can("delete_post", $post->ID),
|
||||
];
|
||||
}
|
||||
|
||||
private static function stats()
|
||||
{
|
||||
$counts = wp_count_posts("post");
|
||||
|
||||
return [
|
||||
"all" => (int) $counts->publish + (int) $counts->draft + (int) $counts->pending + (int) $counts->private + (int) $counts->future,
|
||||
"publish" => (int) $counts->publish,
|
||||
"draft" => (int) $counts->draft,
|
||||
"pending" => (int) $counts->pending,
|
||||
"trash" => (int) ($counts->trash ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
private static function query_status($status)
|
||||
{
|
||||
switch ($status) {
|
||||
case "publish":
|
||||
case "draft":
|
||||
case "pending":
|
||||
case "trash":
|
||||
return $status;
|
||||
case "all":
|
||||
default:
|
||||
return ["publish", "draft", "pending", "private", "future"];
|
||||
}
|
||||
}
|
||||
|
||||
private static function status_label($status)
|
||||
{
|
||||
switch ($status) {
|
||||
case "publish":
|
||||
return __("Published", "aurora-admin");
|
||||
case "draft":
|
||||
return __("Draft", "aurora-admin");
|
||||
case "pending":
|
||||
return __("Pending", "aurora-admin");
|
||||
case "future":
|
||||
return __("Scheduled", "aurora-admin");
|
||||
case "private":
|
||||
return __("Private", "aurora-admin");
|
||||
case "trash":
|
||||
return __("Trash", "aurora-admin");
|
||||
default:
|
||||
return ucfirst($status);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user