\WP_REST_Server::READABLE, 'callback' => [ self::class, 'serve' ], 'permission_callback' => '__return_true', 'args' => [ 'id' => [ 'required' => true, 'sanitize_callback' => 'absint' ], 't' => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ], ], ] ); } public static function serve( \WP_REST_Request $req ) { $id = (int) $req->get_param( 'id' ); $token = (string) $req->get_param( 't' ); $booking = Booking_Repository::find( $id ); if ( ! $booking || ! Token::consume_equals( $booking['reschedule_token'], $token ) ) { return new \WP_Error( 'invalid_token', __( 'Invalid calendar link.', 'bookingistic' ), [ 'status' => 410 ] ); } $ics = ICS_Generator::for_booking( $booking ); $response = new \WP_REST_Response( $ics ); $response->header( 'Content-Type', 'text/calendar; charset=utf-8' ); $response->header( 'Content-Disposition', 'attachment; filename="bookingistic-' . (int) $booking['id'] . '.ics"' ); return $response; } }