diff --git a/src/AKSRT/Forum/Forum.php b/src/AKSRT/Forum/Forum.php index 9f07fa09..23f7eded 100644 --- a/src/AKSRT/Forum/Forum.php +++ b/src/AKSRT/Forum/Forum.php @@ -88,6 +88,13 @@ class Forum { private function draft_service(): DraftService { if (!$this->draft_svc) { + // Composer PSR-4: AKSRT\Forum\DraftService → src/AKSRT/Forum/DraftService.php + // Never require legacy class-aksrt-forum-draft-service.php. + if (!class_exists(DraftService::class, true)) { + throw new \RuntimeException( + 'AKSRT\\Forum\\DraftService missing; deploy src/AKSRT/Forum/DraftService.php and run composer dump-autoload if needed' + ); + } $this->draft_svc = new DraftService($this); } return $this->draft_svc; @@ -777,15 +784,47 @@ class Forum { } public function ajax_save_draft(): void { - $this->draft_service()->ajax_save_draft(); + $this->run_draft_ajax(static function (self $forum): void { + $forum->draft_service()->ajax_save_draft(); + }); } public function ajax_load_draft(): void { - $this->draft_service()->ajax_load_draft(); + $this->run_draft_ajax(static function (self $forum): void { + $forum->draft_service()->ajax_load_draft(); + }); } public function ajax_delete_draft(): void { - $this->draft_service()->ajax_delete_draft(); + $this->run_draft_ajax(static function (self $forum): void { + $forum->draft_service()->ajax_delete_draft(); + }); + } + + /** + * Draft AJAX must never leak WP recovery HTML — return JSON on Throwable. + */ + private function run_draft_ajax(callable $callback): void { + try { + $callback($this); + } catch (\Throwable $e) { + if (defined('WP_DEBUG') && WP_DEBUG) { + error_log('[AKSRT forum draft ajax] ' . $e->getMessage() . ' @ ' . $e->getFile() . ':' . $e->getLine()); + } + // Prefer JSON even when autoload/require still broken on a partial deploy. + if (!headers_sent()) { + status_header(500); + } + wp_send_json_error([ + 'message' => sprintf( + /* translators: %s: exception message */ + __('草稿操作失败:%s', 'aksrt'), + $e->getMessage() + ), + 'file' => basename($e->getFile()), + 'line' => $e->getLine(), + ], 500); + } } public function ajax_search_boards(): void {