use std::path::Path;
use crate::core::validators::{
FileExtensionValidator, ProhibitNullCharactersValidator, ValidationError, Validator,
};
use super::FieldType;
pub fn validate_file_field(
path: &Path,
allowed_extensions: Option<&[&str]>,
) -> Result<(), ValidationError> {
let rendered = path.display().to_string();
if rendered.is_empty() {
return Err(ValidationError::new(
"File paths cannot be empty.",
"required",
));
}
ProhibitNullCharactersValidator::default().validate(&rendered)?;
if let Some(allowed_extensions) = allowed_extensions {
FileExtensionValidator::new(allowed_extensions.iter().copied()).validate(&path)?;
}
Ok(())
}
#[must_use]
pub fn upload_to_path(upload_to: &str, filename: &str) -> String {
let base = upload_to.trim_end_matches('/');
if base.is_empty() {
filename.to_string()
} else {
format!("{base}/{filename}")
}
}
#[must_use]
pub fn db_type(field: &FieldType, vendor: &str) -> Option<String> {
let _ = vendor;
match field {
FieldType::File { .. } | FieldType::Image { .. } | FieldType::FilePath { .. } => {
Some("varchar(100)".to_string())
}
_ => None,
}
}
pub fn get_prep_value(value: &str) -> Result<String, ValidationError> {
let path = Path::new(value);
validate_file_field(path, None)?;
Ok(path.display().to_string())
}
pub fn from_db_value(value: &str) -> Result<String, ValidationError> {
get_prep_value(value)
}
#[must_use]
pub fn formfield(field: &FieldType) -> Option<&'static str> {
match field {
FieldType::File { .. } => Some("FileField"),
FieldType::Image { .. } => Some("ImageField"),
FieldType::FilePath { .. } => Some("FilePathField"),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::{FieldType, db_type, formfield, from_db_value, get_prep_value};
#[test]
fn db_type_for_sqlite_uses_varchar() {
let field = FieldType::File {
upload_to: "uploads".to_string(),
};
assert_eq!(db_type(&field, "sqlite").as_deref(), Some("varchar(100)"));
}
#[test]
fn get_prep_value_normalizes_file_path() {
let prepared = get_prep_value("media/avatar.png").expect("file paths should validate");
assert_eq!(prepared, "media/avatar.png");
}
#[test]
fn from_db_value_returns_path_string() {
let stored = from_db_value("media/image.jpg").expect("stored file path should round-trip");
assert_eq!(stored, "media/image.jpg");
}
#[test]
fn formfield_returns_correct_type() {
let field = FieldType::Image {
upload_to: "images".to_string(),
};
assert_eq!(formfield(&field), Some("ImageField"));
}
}