From a308f96837711a602c3b11f8bc5c571557a7233e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Oct 2026 21:41:38 +0800 Subject: [PATCH] fix(ticket): route attachment upload through UserController singleton The static-array callable pointed at an instance method, which PHP 8 rejects as non-callable, so WP answered every upload with rest_invalid_handler. Co-Authored-By: Claude Fable 5 --- src/Ticket/TicketRest.php | 10 +++++++++- .../widget-system/ticket-permission-contract.test.cjs | 6 ++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Ticket/TicketRest.php b/src/Ticket/TicketRest.php index c277bd94..3a7ec2c3 100644 --- a/src/Ticket/TicketRest.php +++ b/src/Ticket/TicketRest.php @@ -91,7 +91,7 @@ final class TicketRest { register_rest_route($namespace, '/ticket/upload-attachment', [ 'methods' => \WP_REST_Server::CREATABLE, - 'callback' => [\AKSRT\Admin\UserController::class, 'rest_upload_comment_image'], + 'callback' => [$this, 'upload_attachment'], 'permission_callback' => [$this, 'require_attachment_upload'], ]); } @@ -145,6 +145,14 @@ final class TicketRest { return true; } + /** + * 复用评论图片上传 handler。它是实例方法,必须经单例调用: + * [UserController::class, '...'] 在 PHP 8 下 is_callable() 为 false,WP 会报「路由处理程序无效」。 + */ + public function upload_attachment(\WP_REST_Request $request) { + return \AKSRT\Admin\UserController::get_instance()->rest_upload_comment_image($request); + } + public function list_tickets(\WP_REST_Request $request) { if (!$this->ensure_enabled()) { return $this->disabled(); diff --git a/tests/widget-system/ticket-permission-contract.test.cjs b/tests/widget-system/ticket-permission-contract.test.cjs index ee24819e..bc24eebf 100644 --- a/tests/widget-system/ticket-permission-contract.test.cjs +++ b/tests/widget-system/ticket-permission-contract.test.cjs @@ -54,8 +54,10 @@ test('attachment upload permission is gated on the ticket attachment switch', () assert.match(body, /TicketSettings::enabled\(\)/); assert.match(body, /TicketSettings::attachment_enabled\(\)/); - // 复用评论图片上传 handler,不自建上传链路。 - assert.match(rest, /callback' => \[\\AKSRT\\Admin\\UserController::class, 'rest_upload_comment_image'\]/); + // 复用评论图片上传 handler,不自建上传链路;实例方法必须经单例调用(静态数组 callable 在 PHP 8 不可调用)。 + assert.match(rest, /'callback' => \[\$this, 'upload_attachment'\]/); + assert.match(rest, /UserController::get_instance\(\)->rest_upload_comment_image\(\$request\)/); + assert.doesNotMatch(rest, /UserController::class, 'rest_upload_comment_image'/); // 上传路由挂在 /ticket/upload-attachment(与 /report/upload-image 同构)。 assert.match(rest, /'\/ticket\/upload-attachment'/); });