Extract timestamp configuration from a model class. Reads three sources: - `$timestamps` property — `true` (default) or `false`. - `CREATED_AT` constant — column name string or `null`. - `UPDATED_AT` constant — column name string or `null`. Returns `(timestamps, created_at_name, updated_at_name)` using the same `Option` semantics as `LaravelMetadata`: outer `None` means "not declared", `Some(No
(
members: impl Iterator<Item = &'a ClassLikeMember<'a>>,
content: &str,
)
| 610 | /// same `Option` semantics as `LaravelMetadata`: outer `None` means |
| 611 | /// "not declared", `Some(None)` means "explicitly `null`". |
| 612 | fn extract_timestamp_config<'a>( |
| 613 | members: impl Iterator<Item = &'a ClassLikeMember<'a>>, |
| 614 | content: &str, |
| 615 | ) -> (Option<bool>, Option<Option<String>>, Option<Option<String>>) { |
| 616 | let mut timestamps: Option<bool> = None; |
| 617 | let mut created_at: Option<Option<String>> = None; |
| 618 | let mut updated_at: Option<Option<String>> = None; |
| 619 | |
| 620 | for member in members { |
| 621 | match member { |
| 622 | ClassLikeMember::Property(Property::Plain(plain)) => { |
| 623 | for item in plain.items.iter() { |
| 624 | let var_name = item.variable().name.to_string(); |
| 625 | let stripped = var_name.strip_prefix('$').unwrap_or(&var_name); |
| 626 | if stripped != "timestamps" { |
| 627 | continue; |
| 628 | } |
| 629 | if let PropertyItem::Concrete(concrete) = item { |
| 630 | let span = concrete.value.span(); |
| 631 | let start = span.start.offset as usize; |
| 632 | let end = span.end.offset as usize; |
| 633 | if let Some(text) = content.get(start..end) { |
| 634 | let trimmed = text.trim(); |
| 635 | if trimmed == "false" { |
| 636 | timestamps = Some(false); |
| 637 | } else if trimmed == "true" { |
| 638 | timestamps = Some(true); |
| 639 | } |
| 640 | } |
| 641 | } |
| 642 | } |
| 643 | } |
| 644 | ClassLikeMember::Constant(constant) => { |
| 645 | for item in constant.items.iter() { |
| 646 | let name = item.name.value.to_string(); |
| 647 | if name != "CREATED_AT" && name != "UPDATED_AT" { |
| 648 | continue; |
| 649 | } |
| 650 | let span = item.value.span(); |
| 651 | let start = span.start.offset as usize; |
| 652 | let end = span.end.offset as usize; |
| 653 | let value = content.get(start..end).map(|t| t.trim()); |
| 654 | let parsed = match value { |
| 655 | Some("null") | Some("NULL") => Some(None), |
| 656 | Some(v) => extract_string_literal(v).map(Some), |
| 657 | None => None, |
| 658 | }; |
| 659 | if let Some(val) = parsed { |
| 660 | if name == "CREATED_AT" { |
| 661 | created_at = Some(val); |
| 662 | } else { |
| 663 | updated_at = Some(val); |
| 664 | } |
| 665 | } |
| 666 | } |
| 667 | } |
| 668 | _ => {} |
| 669 | } |
no test coverage detected