use super::HasMany;
pub fn class_to_snake_case(name: &str) -> String {
if name.chars().all(|c| !c.is_uppercase()) {
return name.to_string();
}
let mut result = String::with_capacity(name.len() + 4);
for (i, c) in name.chars().enumerate() {
if c.is_uppercase() && i > 0 {
result.push('_');
}
result.extend(c.to_lowercase());
}
result
}
pub fn default_foreign_key(parent_class: &str) -> String {
let class_name = parent_class
.rsplit(['\\', '/'])
.next()
.unwrap_or(parent_class);
format!("{}_id", class_to_snake_case(class_name))
}
pub fn php_has_many(
parent_class: &str,
child_table: &str,
foreign_key: Option<&str>,
child_pk: Option<&str>,
) -> HasMany {
HasMany {
foreign_key: foreign_key
.map(String::from)
.unwrap_or_else(|| default_foreign_key(parent_class)),
child_model: child_table.to_string(),
child_pk: child_pk
.map(String::from)
.unwrap_or_else(|| "id".to_string()),
}
}
pub fn has_many_sql(child_table: &str, foreign_key: &str, parent_pk_value: &str) -> String {
format!(
"SELECT * FROM {} WHERE {} = {}",
child_table, foreign_key, parent_pk_value
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_snake_single_word() {
assert_eq!(class_to_snake_case("User"), "user");
assert_eq!(class_to_snake_case("Order"), "order");
assert_eq!(class_to_snake_case("Customer"), "customer");
}
#[test]
fn test_snake_multi_word_camel_case() {
assert_eq!(class_to_snake_case("OrderItem"), "order_item");
assert_eq!(class_to_snake_case("UserRole"), "user_role");
assert_eq!(class_to_snake_case("UploadFile"), "upload_file");
}
#[test]
fn test_snake_all_lowercase_unchanged() {
assert_eq!(class_to_snake_case("user"), "user");
assert_eq!(class_to_snake_case("user_id"), "user_id");
assert_eq!(class_to_snake_case(""), "");
}
#[test]
fn test_snake_all_uppercase() {
assert_eq!(class_to_snake_case("URL"), "u_r_l");
assert_eq!(class_to_snake_case("ABC"), "a_b_c");
}
#[test]
fn test_snake_mixed_case() {
assert_eq!(class_to_snake_case("userID"), "user_i_d");
assert_eq!(class_to_snake_case("OrderID"), "order_i_d");
}
#[test]
fn test_default_foreign_key_simple_class() {
assert_eq!(default_foreign_key("User"), "user_id");
assert_eq!(default_foreign_key("Order"), "order_id");
assert_eq!(default_foreign_key("Customer"), "customer_id");
}
#[test]
fn test_default_foreign_key_multi_word_class() {
assert_eq!(default_foreign_key("OrderItem"), "order_item_id");
assert_eq!(default_foreign_key("UserRole"), "user_role_id");
}
#[test]
fn test_default_foreign_key_with_namespace() {
assert_eq!(default_foreign_key("app\\model\\User"), "user_id");
assert_eq!(
default_foreign_key("app\\model\\OrderItem"),
"order_item_id"
);
assert_eq!(default_foreign_key("app/model/User"), "user_id");
}
#[test]
fn test_default_foreign_key_all_uppercase_class() {
assert_eq!(default_foreign_key("URL"), "u_r_l_id");
}
#[test]
fn test_php_has_many_default_foreign_key() {
let rel = php_has_many("User", "orders", None, None);
assert_eq!(rel.foreign_key, "user_id");
assert_eq!(rel.child_model, "orders");
assert_eq!(rel.child_pk, "id");
}
#[test]
fn test_php_has_many_explicit_foreign_key() {
let rel = php_has_many("User", "orders", Some("uid"), None);
assert_eq!(rel.foreign_key, "uid");
assert_eq!(rel.child_model, "orders");
assert_eq!(rel.child_pk, "id");
}
#[test]
fn test_php_has_many_explicit_child_pk() {
let rel = php_has_many("User", "orders", Some("uid"), Some("oid"));
assert_eq!(rel.foreign_key, "uid");
assert_eq!(rel.child_model, "orders");
assert_eq!(rel.child_pk, "oid");
}
#[test]
fn test_php_has_many_multi_word_parent() {
let rel = php_has_many("OrderItem", "order_items", None, None);
assert_eq!(rel.foreign_key, "order_item_id");
assert_eq!(rel.child_model, "order_items");
}
#[test]
fn test_php_has_many_with_namespace_parent() {
let rel = php_has_many("app\\model\\User", "orders", None, None);
assert_eq!(rel.foreign_key, "user_id");
}
#[test]
fn test_has_many_sql_numeric_pk() {
let sql = has_many_sql("orders", "user_id", "1");
assert_eq!(sql, "SELECT * FROM orders WHERE user_id = 1");
}
#[test]
fn test_has_many_sql_string_pk() {
let sql = has_many_sql("orders", "user_id", "'abc-123'");
assert_eq!(sql, "SELECT * FROM orders WHERE user_id = 'abc-123'");
}
#[test]
fn test_has_many_sql_custom_foreign_key() {
let sql = has_many_sql("orders", "uid", "1");
assert_eq!(sql, "SELECT * FROM orders WHERE uid = 1");
}
#[test]
fn test_has_many_sql_multi_word_table() {
let sql = has_many_sql("order_items", "order_id", "1");
assert_eq!(sql, "SELECT * FROM order_items WHERE order_id = 1");
}
#[test]
fn test_has_many_sql_aligns_sz_orm_core_pattern() {
let sql = has_many_sql("orders", "user_id", "1");
assert!(sql.starts_with("SELECT * FROM orders WHERE user_id = "));
}
#[test]
fn test_r5_php_has_many_default_foreign_key_convention() {
assert_eq!(default_foreign_key("User"), "user_id");
assert_eq!(default_foreign_key("Order"), "order_id");
assert_eq!(default_foreign_key("Customer"), "customer_id");
assert_eq!(default_foreign_key("OrderItem"), "order_item_id");
}
#[test]
fn test_r5_php_has_many_explicit_foreign_key_overrides_default() {
let rel = php_has_many("User", "orders", Some("uid"), None);
assert_eq!(rel.foreign_key, "uid");
assert_ne!(rel.foreign_key, default_foreign_key("User"));
}
#[test]
fn test_r5_php_has_many_default_local_key_is_id() {
let rel = php_has_many("User", "orders", None, None);
assert_eq!(rel.child_pk, "id");
}
#[test]
fn test_r5_php_has_many_sql_pattern_matches_think_orm() {
let sql = has_many_sql("orders", "user_id", "1");
assert_eq!(sql, "SELECT * FROM orders WHERE user_id = 1");
}
#[test]
fn test_r5_php_has_many_returns_collection() {
let rel = php_has_many("User", "orders", None, None);
assert!(!rel.child_model.is_empty());
assert!(!rel.foreign_key.is_empty());
assert!(!rel.child_pk.is_empty());
}
#[test]
fn test_r5_php_str_snake_naming_convention() {
assert_eq!(class_to_snake_case("User"), "user");
assert_eq!(class_to_snake_case("OrderItem"), "order_item");
assert_eq!(class_to_snake_case("UploadFile"), "upload_file");
assert_eq!(class_to_snake_case("URL"), "u_r_l");
}
#[test]
fn test_r5_php_has_many_namespace_handling() {
assert_eq!(default_foreign_key("app\\model\\User"), "user_id");
assert_eq!(
default_foreign_key("app\\model\\OrderItem"),
"order_item_id"
);
assert_eq!(default_foreign_key("App\\Model\\User"), "user_id");
}
#[test]
fn test_r5_php_has_many_delegates_to_sz_orm_core() {
let rel = php_has_many("User", "orders", None, None);
let _: &HasMany = &rel;
let relation = sz_orm_core::Relation::HasMany(rel.clone());
assert!(matches!(relation, sz_orm_core::Relation::HasMany(_)));
}
#[test]
fn test_integration_user_has_many_orders() {
let rel = php_has_many("User", "orders", None, None);
assert_eq!(rel.foreign_key, "user_id");
assert_eq!(rel.child_model, "orders");
assert_eq!(rel.child_pk, "id");
let sql = has_many_sql(&rel.child_model, &rel.foreign_key, "1");
assert_eq!(sql, "SELECT * FROM orders WHERE user_id = 1");
}
#[test]
fn test_integration_customer_has_many_contracts() {
let rel = php_has_many("Customer", "contracts", Some("customer_id"), None);
assert_eq!(rel.foreign_key, "customer_id");
assert_eq!(rel.child_model, "contracts");
let sql = has_many_sql(&rel.child_model, &rel.foreign_key, "100");
assert_eq!(sql, "SELECT * FROM contracts WHERE customer_id = 100");
}
#[test]
fn test_integration_dept_has_many_users() {
let rel = php_has_many("Dept", "users", None, None);
assert_eq!(rel.foreign_key, "dept_id");
assert_eq!(rel.child_model, "users");
let sql = has_many_sql(&rel.child_model, &rel.foreign_key, "5");
assert_eq!(sql, "SELECT * FROM users WHERE dept_id = 5");
}
}