WP_REST_Server::READABLE, 'callback' => array( __CLASS__, 'get_doctors' ), 'permission_callback' => array( __CLASS__, 'check_read_permission' ), 'args' => array( 'page' => array( 'description' => 'Page number for pagination', 'type' => 'integer', 'default' => 1, 'minimum' => 1, 'sanitize_callback' => 'absint', ), 'per_page' => array( 'description' => 'Number of doctors per page', 'type' => 'integer', 'default' => 10, 'minimum' => 1, 'maximum' => 100, 'sanitize_callback' => 'absint', ), 'status' => array( 'description' => 'Filter by doctor status', 'type' => 'string', 'enum' => array( 'active', 'inactive', 'suspended' ), ), 'specialty' => array( 'description' => 'Filter by specialty', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'clinic_id' => array( 'description' => 'Filter by clinic ID', 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), )); // Create new doctor register_rest_route( self::NAMESPACE, '/doctors', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( __CLASS__, 'create_doctor' ), 'permission_callback' => array( __CLASS__, 'check_create_permission' ), 'args' => array( 'first_name' => array( 'description' => 'Doctor first name', 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => array( __CLASS__, 'validate_required_string' ), ), 'last_name' => array( 'description' => 'Doctor last name', 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => array( __CLASS__, 'validate_required_string' ), ), 'email' => array( 'description' => 'Doctor email address', 'type' => 'string', 'required' => true, 'format' => 'email', 'sanitize_callback' => 'sanitize_email', 'validate_callback' => array( __CLASS__, 'validate_email' ), ), 'phone' => array( 'description' => 'Doctor phone number', 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ), 'specialty' => array( 'description' => 'Doctor medical specialty', 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ), 'license_number' => array( 'description' => 'Medical license number', 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ), 'clinic_id' => array( 'description' => 'Primary clinic ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), 'qualifications' => array( 'description' => 'Doctor qualifications', 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field', ), 'experience_years' => array( 'description' => 'Years of experience', 'type' => 'integer', 'minimum' => 0, 'sanitize_callback' => 'absint', ), 'consultation_fee' => array( 'description' => 'Consultation fee', 'type' => 'number', 'minimum' => 0, ), 'schedule' => array( 'description' => 'Doctor availability schedule', 'type' => 'object', ), ), )); // Get specific doctor register_rest_route( self::NAMESPACE, '/doctors/(?P\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( __CLASS__, 'get_doctor' ), 'permission_callback' => array( __CLASS__, 'check_read_permission' ), 'args' => array( 'id' => array( 'description' => 'Doctor ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), ), )); // Update doctor register_rest_route( self::NAMESPACE, '/doctors/(?P\d+)', array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( __CLASS__, 'update_doctor' ), 'permission_callback' => array( __CLASS__, 'check_update_permission' ), 'args' => array( 'id' => array( 'description' => 'Doctor ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), 'first_name' => array( 'description' => 'Doctor first name', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'last_name' => array( 'description' => 'Doctor last name', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'email' => array( 'description' => 'Doctor email address', 'type' => 'string', 'format' => 'email', 'sanitize_callback' => 'sanitize_email', ), 'phone' => array( 'description' => 'Doctor phone number', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'specialty' => array( 'description' => 'Doctor medical specialty', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'license_number' => array( 'description' => 'Medical license number', 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'qualifications' => array( 'description' => 'Doctor qualifications', 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field', ), 'experience_years' => array( 'description' => 'Years of experience', 'type' => 'integer', 'minimum' => 0, 'sanitize_callback' => 'absint', ), 'consultation_fee' => array( 'description' => 'Consultation fee', 'type' => 'number', 'minimum' => 0, ), 'status' => array( 'description' => 'Doctor status', 'type' => 'string', 'enum' => array( 'active', 'inactive', 'suspended' ), ), 'schedule' => array( 'description' => 'Doctor availability schedule', 'type' => 'object', ), ), )); // Delete doctor register_rest_route( self::NAMESPACE, '/doctors/(?P\d+)', array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( __CLASS__, 'delete_doctor' ), 'permission_callback' => array( __CLASS__, 'check_delete_permission' ), 'args' => array( 'id' => array( 'description' => 'Doctor ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), 'force' => array( 'description' => 'Force delete (bypass soft delete)', 'type' => 'boolean', 'default' => false, ), ), )); // Search doctors register_rest_route( self::NAMESPACE, '/doctors/search', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( __CLASS__, 'search_doctors' ), 'permission_callback' => array( __CLASS__, 'check_read_permission' ), 'args' => array( 'q' => array( 'description' => 'Search query', 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ), 'fields' => array( 'description' => 'Fields to search in', 'type' => 'array', 'items' => array( 'type' => 'string', 'enum' => array( 'name', 'email', 'specialty', 'license_number' ), ), 'default' => array( 'name', 'specialty' ), ), 'limit' => array( 'description' => 'Maximum results to return', 'type' => 'integer', 'default' => 10, 'minimum' => 1, 'maximum' => 50, 'sanitize_callback' => 'absint', ), ), )); // Get doctor schedule register_rest_route( self::NAMESPACE, '/doctors/(?P\d+)/schedule', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( __CLASS__, 'get_doctor_schedule' ), 'permission_callback' => array( __CLASS__, 'check_read_permission' ), 'args' => array( 'id' => array( 'description' => 'Doctor ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), 'date_from' => array( 'description' => 'Start date (YYYY-MM-DD)', 'type' => 'string', 'format' => 'date', ), 'date_to' => array( 'description' => 'End date (YYYY-MM-DD)', 'type' => 'string', 'format' => 'date', ), ), )); // Update doctor schedule register_rest_route( self::NAMESPACE, '/doctors/(?P\d+)/schedule', array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( __CLASS__, 'update_doctor_schedule' ), 'permission_callback' => array( __CLASS__, 'check_update_permission' ), 'args' => array( 'id' => array( 'description' => 'Doctor ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), 'schedule' => array( 'description' => 'Doctor schedule data', 'type' => 'object', 'required' => true, ), ), )); // Get doctor statistics register_rest_route( self::NAMESPACE, '/doctors/(?P\d+)/stats', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( __CLASS__, 'get_doctor_stats' ), 'permission_callback' => array( __CLASS__, 'check_read_permission' ), 'args' => array( 'id' => array( 'description' => 'Doctor ID', 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), 'period' => array( 'description' => 'Statistics period', 'type' => 'string', 'enum' => array( 'week', 'month', 'quarter', 'year' ), 'default' => 'month', ), ), )); // Bulk operations register_rest_route( self::NAMESPACE, '/doctors/bulk', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( __CLASS__, 'bulk_operations' ), 'permission_callback' => array( __CLASS__, 'check_create_permission' ), 'args' => array( 'action' => array( 'description' => 'Bulk action to perform', 'type' => 'string', 'required' => true, 'enum' => array( 'activate', 'deactivate', 'suspend', 'delete' ), ), 'doctor_ids' => array( 'description' => 'Array of doctor IDs', 'type' => 'array', 'required' => true, 'items' => array( 'type' => 'integer', ), 'minItems' => 1, ), ), )); } /** * Get doctors list. */ public static function get_doctors( WP_REST_Request $request ) { try { $page = $request->get_param( 'page' ); $per_page = $request->get_param( 'per_page' ); $offset = ( $page - 1 ) * $per_page; $args = array( 'limit' => $per_page, 'offset' => $offset, ); // Add filters $status = $request->get_param( 'status' ); if ( $status ) { $args['status'] = $status; } $specialty = $request->get_param( 'specialty' ); if ( $specialty ) { $args['specialty'] = $specialty; } $clinic_id = $request->get_param( 'clinic_id' ); if ( $clinic_id ) { $args['clinic_id'] = $clinic_id; } $result = Doctor_Service::get_doctors( $args ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } $total_doctors = Doctor_Service::get_doctors_count( $args ); $total_pages = ceil( $total_doctors / $per_page ); $response = new WP_REST_Response( array( 'success' => true, 'data' => $result, 'meta' => array( 'total' => $total_doctors, 'pages' => $total_pages, 'current' => $page, 'per_page' => $per_page, ), ), 200 ); return $response; } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Create new doctor. */ public static function create_doctor( WP_REST_Request $request ) { try { $doctor_data = array( 'first_name' => $request->get_param( 'first_name' ), 'last_name' => $request->get_param( 'last_name' ), 'email' => $request->get_param( 'email' ), 'phone' => $request->get_param( 'phone' ), 'specialty' => $request->get_param( 'specialty' ), 'license_number' => $request->get_param( 'license_number' ), 'clinic_id' => $request->get_param( 'clinic_id' ), 'qualifications' => $request->get_param( 'qualifications' ), 'experience_years' => $request->get_param( 'experience_years' ), 'consultation_fee' => $request->get_param( 'consultation_fee' ), 'schedule' => $request->get_param( 'schedule' ), ); // Validate input data $validation_result = Input_Validator::validate_doctor_data( $doctor_data ); if ( is_wp_error( $validation_result ) ) { return Error_Handler::handle_service_error( $validation_result ); } $result = Doctor_Service::create_doctor( $doctor_data ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'message' => 'Doctor created successfully', 'data' => $result, ), 201 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Get specific doctor. */ public static function get_doctor( WP_REST_Request $request ) { try { $doctor_id = $request->get_param( 'id' ); $result = Doctor_Service::get_doctor( $doctor_id ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Update doctor. */ public static function update_doctor( WP_REST_Request $request ) { try { $doctor_id = $request->get_param( 'id' ); $update_data = array(); // Only include parameters that were actually sent $params = array( 'first_name', 'last_name', 'email', 'phone', 'specialty', 'license_number', 'qualifications', 'experience_years', 'consultation_fee', 'status', 'schedule' ); foreach ( $params as $param ) { if ( $request->has_param( $param ) ) { $update_data[$param] = $request->get_param( $param ); } } if ( empty( $update_data ) ) { return new WP_REST_Response( array( 'success' => false, 'message' => 'No data provided for update', ), 400 ); } // Validate input data $validation_result = Input_Validator::validate_doctor_data( $update_data, true ); if ( is_wp_error( $validation_result ) ) { return Error_Handler::handle_service_error( $validation_result ); } $result = Doctor_Service::update_doctor( $doctor_id, $update_data ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'message' => 'Doctor updated successfully', 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Delete doctor. */ public static function delete_doctor( WP_REST_Request $request ) { try { $doctor_id = $request->get_param( 'id' ); $force = $request->get_param( 'force' ); $result = Doctor_Service::delete_doctor( $doctor_id, $force ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'message' => $force ? 'Doctor permanently deleted' : 'Doctor deactivated successfully', 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Search doctors. */ public static function search_doctors( WP_REST_Request $request ) { try { $query = $request->get_param( 'q' ); $fields = $request->get_param( 'fields' ); $limit = $request->get_param( 'limit' ); $result = Doctor_Service::search_doctors( $query, $fields, $limit ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'data' => $result, 'meta' => array( 'query' => $query, 'fields' => $fields, 'results' => count( $result ), ), ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Get doctor schedule. */ public static function get_doctor_schedule( WP_REST_Request $request ) { try { $doctor_id = $request->get_param( 'id' ); $date_from = $request->get_param( 'date_from' ); $date_to = $request->get_param( 'date_to' ); $result = Doctor_Service::get_doctor_schedule( $doctor_id, $date_from, $date_to ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Update doctor schedule. */ public static function update_doctor_schedule( WP_REST_Request $request ) { try { $doctor_id = $request->get_param( 'id' ); $schedule = $request->get_param( 'schedule' ); $result = Doctor_Service::update_doctor_schedule( $doctor_id, $schedule ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'message' => 'Doctor schedule updated successfully', 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Get doctor statistics. */ public static function get_doctor_stats( WP_REST_Request $request ) { try { $doctor_id = $request->get_param( 'id' ); $period = $request->get_param( 'period' ); $result = Doctor_Service::get_doctor_statistics( $doctor_id, $period ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Handle bulk operations. */ public static function bulk_operations( WP_REST_Request $request ) { try { $action = $request->get_param( 'action' ); $doctor_ids = $request->get_param( 'doctor_ids' ); $result = Doctor_Service::bulk_update_doctors( $doctor_ids, $action ); if ( is_wp_error( $result ) ) { return Error_Handler::handle_service_error( $result ); } return new WP_REST_Response( array( 'success' => true, 'message' => sprintf( 'Bulk operation "%s" completed successfully', $action ), 'data' => $result, ), 200 ); } catch ( Exception $e ) { return Error_Handler::handle_exception( $e ); } } /** * Check read permission. */ public static function check_read_permission( WP_REST_Request $request ) { return Permission_Service::can_read_doctors(); } /** * Check create permission. */ public static function check_create_permission( WP_REST_Request $request ) { return Permission_Service::can_manage_doctors(); } /** * Check update permission. */ public static function check_update_permission( WP_REST_Request $request ) { $doctor_id = $request->get_param( 'id' ); return Permission_Service::can_edit_doctor( $doctor_id ); } /** * Check delete permission. */ public static function check_delete_permission( WP_REST_Request $request ) { $doctor_id = $request->get_param( 'id' ); return Permission_Service::can_delete_doctor( $doctor_id ); } /** * Validate required string parameter. */ public static function validate_required_string( $value, $request, $param ) { if ( empty( $value ) || ! is_string( $value ) ) { return new WP_Error( 'invalid_param', sprintf( 'Parameter "%s" is required and must be a non-empty string.', $param ) ); } return true; } /** * Validate email parameter. */ public static function validate_email( $value, $request, $param ) { if ( ! is_email( $value ) ) { return new WP_Error( 'invalid_email', 'Please provide a valid email address.' ); } return true; } }