/** * Verify if a list of filters applies to the calendar data object * * The calendarData object must be a valid iCalendar blob. The list of * filters must be formatted as parsed by Sabre_CalDAV_Plugin::parseCalendarQueryFilters * * @param string $calendarData * @param array $filters * @return bool */ public function validateFilters($calendarData, $filters) { // We are converting the calendar object to an XML structure // This makes it far easier to parse $xCalendarData = Sabre_CalDAV_ICalendarUtil::toXCal($calendarData); $xml = simplexml_load_string($xCalendarData); $xml->registerXPathNamespace('c', 'urn:ietf:params:xml:ns:xcal'); foreach ($filters as $xpath => $filter) { // if-not-defined comes first if (isset($filter['is-not-defined'])) { if (!$xml->xpath($xpath)) { continue; } else { return false; } } $elem = $xml->xpath($xpath); if (!$elem) { return false; } $elem = $elem[0]; if (isset($filter['time-range'])) { switch ($elem->getName()) { case 'vevent': $result = $this->validateTimeRangeFilterForEvent($xml, $xpath, $filter); if ($result === false) { return false; } break; case 'vtodo': $result = $this->validateTimeRangeFilterForTodo($xml, $xpath, $filter); if ($result === false) { return false; } break; case 'vjournal': case 'vfreebusy': case 'valarm': // TODO: not implemented break; /* case 'vjournal' : $result = $this->validateTimeRangeFilterForJournal($xml,$xpath,$filter); if ($result===false) return false; break; case 'vfreebusy' : $result = $this->validateTimeRangeFilterForFreeBusy($xml,$xpath,$filter); if ($result===false) return false; break; case 'valarm' : $result = $this->validateTimeRangeFilterForAlarm($xml,$xpath,$filter); if ($result===false) return false; break; */ } } if (isset($filter['text-match'])) { $currentString = (string) $elem; $isMatching = Sabre_DAV_StringUtil::textMatch($currentString, $filter['text-match']['value'], $filter['text-match']['collation']); if ($filter['text-match']['negate-condition'] && $isMatching) { return false; } if (!$filter['text-match']['negate-condition'] && !$isMatching) { return false; } } } return true; }
/** * Validates if a text-filter can be applied to a specific property. * * @param array $texts * @param array $filters * @param string $test * @return bool */ protected function validateTextMatches(array $texts, array $filters, $test) { foreach ($filters as $filter) { $success = false; foreach ($texts as $haystack) { $success = Sabre_DAV_StringUtil::textMatch($haystack, $filter['value'], $filter['collation'], $filter['match-type']); // Breaking on the first match if ($success) { break; } } if ($filter['negate-condition']) { $success = !$success; } if ($success && $test === 'anyof') { return true; } if (!$success && $test == 'allof') { return false; } } // If we got all the way here, it means we haven't been able to // determine early if the test failed or not. // // This implies for 'anyof' that the test failed, and for 'allof' that // we succeeded. Sounds weird, but makes sense. return $test === 'allof'; }
/** * This method checks the validity of a text-match. * * A single text-match should be specified as well as the specific property * or parameter we need to validate. * * @param Sabre_VObject_Node $parent * @param array $textMatch * @return bool */ protected function validateTextMatch(Sabre_VObject_Node $parent, array $textMatch) { $value = (string) $parent; $isMatching = Sabre_DAV_StringUtil::textMatch($value, $textMatch['value'], $textMatch['collation']); return $textMatch['negate-condition'] xor $isMatching; }