diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_query/elements.rs b/crates/carddav/src/addressbook/methods/report/addressbook_query/elements.rs index bb351bf..03d5c4d 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_query/elements.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_query/elements.rs @@ -2,6 +2,7 @@ use crate::{ address_object::AddressObjectPropWrapperName, addressbook::methods::report::addressbook_query::PropFilterElement, }; +use ical::property::Property; use rustical_dav::xml::{PropfindType, TextMatchElement}; use rustical_ical::{AddressObject, UtcDateTime}; use rustical_xml::XmlDeserialize; @@ -28,6 +29,22 @@ pub struct ParamFilterElement { pub(crate) name: String, } +impl ParamFilterElement { + pub fn match_property(&self, prop: &Property) -> bool { + let Some(param) = prop.get_param(&self.name) else { + return self.is_not_defined.is_some(); + }; + if self.is_not_defined.is_some() { + return false; + } + + let Some(text_match) = self.text_match.as_ref() else { + return true; + }; + text_match.match_text(param) + } +} + #[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] #[allow(dead_code)] // diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_query/prop_filter.rs b/crates/carddav/src/addressbook/methods/report/addressbook_query/prop_filter.rs index 6c947f0..8535d49 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_query/prop_filter.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_query/prop_filter.rs @@ -35,7 +35,7 @@ pub struct PropFilterElement { impl PropFilterElement { pub fn match_component(&self, comp: &impl PropFilterable) -> bool { let property = comp.get_property(&self.name); - let _property = match (self.is_not_defined.is_some(), property) { + let property = match (self.is_not_defined.is_some(), property) { // We are the component that's not supposed to be defined (true, Some(_)) // We don't match @@ -45,22 +45,28 @@ impl PropFilterElement { (false, Some(property)) => property }; - let _allof = match (self.allof.is_some(), self.anyof.is_some()) { + let allof = match (self.allof.is_some(), self.anyof.is_some()) { (true, false) => true, (false, _) => false, (true, true) => panic!("wat"), }; - // TODO: IMPLEMENT - // if let Some(text_match) = &self.text_match - // && !text_match.match_property(property) - // { - // return false; - // } + let text_matches = self + .text_match + .iter() + .map(|text_match| text_match.match_property(property)); - // TODO: param-filter + let param_matches = self + .param_filter + .iter() + .map(|param_filter| param_filter.match_property(property)); + let mut matches = text_matches.chain(param_matches); - true + if allof { + matches.all(|a| a) + } else { + matches.any(|a| a) + } } } diff --git a/crates/dav/src/xml/text_match.rs b/crates/dav/src/xml/text_match.rs index e5e5d0a..a8db120 100644 --- a/crates/dav/src/xml/text_match.rs +++ b/crates/dav/src/xml/text_match.rs @@ -115,7 +115,7 @@ pub struct TextMatchElement { impl TextMatchElement { #[must_use] - pub fn match_property(&self, property: &Property) -> bool { + pub fn match_text(&self, haystack: &str) -> bool { let Self { collation, negate_condition, @@ -123,14 +123,15 @@ impl TextMatchElement { match_type, } = self; - let matches = property - .value - .as_ref() - .is_some_and(|haystack| match_type.match_text(collation, needle, haystack)); - + let matches = match_type.match_text(collation, needle, haystack); // XOR negate_condition.0 ^ matches } + #[must_use] + pub fn match_property(&self, property: &Property) -> bool { + let text = property.value.as_deref().unwrap_or(""); + self.match_text(text) + } } #[cfg(test)]