\d+)/reservation'; public function register_routes(): void { register_rest_route($this->namespace, $this->resource_name, [ 'methods' => 'GET', 'callback' => [$this, 'by_timetable'], 'permission_callback' => [RsvRestPolicy::class, 'admin'], ]); register_rest_route($this->namespace, '/timetable-reservation/accept/(?P[a-zA-Z0-9]+)', [ 'methods' => 'GET', 'callback' => [$this, 'accept'], // Capability URL: authorised by the secret confirmation code, which // accept() validates against the database before changing state. 'permission_callback' => [RsvRestPolicy::class, 'open'], ]); register_rest_route($this->namespace, '/timetable-reservation/refuse/(?P[a-zA-Z0-9]+)', [ 'methods' => 'GET', 'callback' => [$this, 'refuse'], // Capability URL: authorised by the secret confirmation code, which // refuse() validates against the database before changing state. 'permission_callback' => [RsvRestPolicy::class, 'open'], ]); } public function by_timetable(WP_REST_Request $request): WP_REST_Response { [$skip, $limit] = self::paging($request); $timetable_id = (int) $request->get_param('id'); $service = new RsvTimetableReservationService(); return $this->paged_response( $service->get_by_timetable($timetable_id, $limit, $skip), $service->count_by_timetable($timetable_id) ); } function accept(WP_REST_Request $request) { try { $service = new RsvTimetableReservationService(); $service->accept($request->get_param('code')); return new WP_REST_Response(['status' => 'accepted'], 200); } catch (InvalidArgumentException $e) { return new WP_REST_Response(['error' => 'Invalid or expired confirmation code.'], 404); } } function refuse(WP_REST_Request $request) { try { $service = new RsvTimetableReservationService(); $service->refuse($request->get_param('code')); return new WP_REST_Response(['status' => 'refused'], 200); } catch (InvalidArgumentException $e) { return new WP_REST_Response(['error' => 'Invalid or expired confirmation code.'], 404); } } }