\WP_REST_Server::READABLE, 'callback' => [$this, 'index'], 'permission_callback' => $permission, ], [ 'methods' => \WP_REST_Server::CREATABLE, 'callback' => [$this, 'create'], 'permission_callback' => $permission, ], ]); register_rest_route(self::NAMESPACE, '/pages/(?P\d+)', [ [ 'methods' => \WP_REST_Server::READABLE, 'callback' => [$this, 'show'], 'permission_callback' => $permission, ], [ 'methods' => \WP_REST_Server::EDITABLE, 'callback' => [$this, 'update'], 'permission_callback' => $permission, ], [ 'methods' => \WP_REST_Server::DELETABLE, 'callback' => [$this, 'delete'], 'permission_callback' => $permission, ], ]); } public function canManage(): bool { return current_user_can('manage_options'); } public function index(): \WP_REST_Response { return new \WP_REST_Response(array_map([$this, 'present'], PageRepository::rows())); } public function show(\WP_REST_Request $request) { $row = $this->row((int) $request['id']); return $row ? new \WP_REST_Response($this->present($row)) : $this->notFound(); } public function create(\WP_REST_Request $request) { $saved = $this->save($request, ['page' => SubpageCreate::SLUG]); if ($saved instanceof \WP_Error) { return $saved; } return $this->saved($saved, 201); } public function update(\WP_REST_Request $request) { $id = (int) $request['id']; if (!$this->row($id)) { return $this->notFound(); } $saved = $this->save($request, ['page' => SubpageEdit::SLUG, 'optionpage' => (string) $id]); if ($saved instanceof \WP_Error) { return $saved; } // Shown as a notice when the editor reloads. Flash::add(['pages_updated' => true]); return $this->saved($saved, 200); } public function delete(\WP_REST_Request $request) { $id = (int) $request['id']; if (!$this->row($id)) { return $this->notFound(); } Data::deletePage($id); return new \WP_REST_Response(['id' => $id, 'deleted' => true]); } /** * @return array{id: int, created: bool}|\WP_Error */ private function save(\WP_REST_Request $request, array $get) { $payload = $request->get_json_params(); $payload = is_array($payload) && $payload ? $payload : $request->get_body_params(); // The save flow was written against the slashed $_POST of WordPress. $payload = wp_slash($payload); $this->loadAdminMenu(); try { return Request::run($payload, $get, function () { return (new PageSaver())->save(new Validation()); }); } catch (PageInvalid $invalid) { return $this->invalid($invalid->errors()); } catch (ValidationFailed $failure) { return $this->invalid([['field' => '', 'code' => 'rejected', 'message' => $failure->getMessage()]]); } } /** * `$GLOBALS['menu']` only exists on admin screens; the rules fall back to the list stored by the plugin. */ private function loadAdminMenu(): void { if (empty($GLOBALS['menu'])) { $GLOBALS['menu'] = (array) get_option('aop_admin_menu_list', []); } } private function saved(array $saved, int $status): \WP_REST_Response { return new \WP_REST_Response([ 'id' => $saved['id'], 'created' => $saved['created'], 'redirect' => add_query_arg('optionpage', $saved['id'], SubpageEdit::url()), ], $status); } private function invalid(array $errors): \WP_Error { return new \WP_Error( 'aop_invalid_page', $errors ? $errors[0]['message'] : __('The page is not valid.', 'admin-options-pages'), ['status' => 400, 'errors' => $errors] ); } private function notFound(): \WP_Error { return new \WP_Error('aop_page_not_found', __('This page does not exist.', 'admin-options-pages'), ['status' => 404]); } private function row(int $id) { return PageRepository::rowsById($id)[0] ?? null; } private function present(object $row): array { return [ 'id' => (int) $row->id, 'time' => $row->time, 'menu_slug' => $row->menu_slug, 'page_value' => PageRepository::decode($row->page_value), ]; } }