use crate::php_type::PhpType;
use crate::types::{ClassInfo, MethodInfo};
use super::helpers::camel_to_snake;
const ATTRIBUTE_CAST_FQN: &str = "Illuminate\\Database\\Eloquent\\Casts\\Attribute";
pub(super) fn is_legacy_accessor(method: &MethodInfo) -> bool {
let name = &method.name;
if !name.starts_with("get") || !name.ends_with("Attribute") {
return false;
}
let middle = &name[3..name.len() - 9]; if middle.is_empty() {
return false;
}
middle.starts_with(|c: char| c.is_uppercase())
}
pub(super) fn legacy_accessor_property_name(method_name: &str) -> String {
let middle = &method_name[3..method_name.len() - 9];
camel_to_snake(middle)
}
pub(super) fn is_modern_accessor(method: &MethodInfo) -> bool {
match method.return_type.as_ref() {
Some(rt) => {
if let Some(base) = rt.base_name() {
base == ATTRIBUTE_CAST_FQN || base == "Attribute"
} else {
false
}
}
None => false,
}
}
pub(super) fn extract_modern_accessor_type(method: &MethodInfo) -> PhpType {
if let Some(rt) = method.return_type.as_ref()
&& let PhpType::Generic(_, args) = rt
&& let Some(first) = args.first()
&& !matches!(first, PhpType::Named(s) | PhpType::Raw(s) if s.is_empty())
{
return first.clone();
}
PhpType::mixed()
}
pub(crate) fn is_accessor_method(class: &ClassInfo, method_name: &str) -> bool {
let method = match class.methods.iter().find(|m| m.name == method_name) {
Some(m) => m,
None => return false,
};
is_legacy_accessor(method) || is_modern_accessor(method)
}
#[cfg(test)]
#[path = "accessors_tests.rs"]
mod tests;