/** * This function handles the calendar-query REPORT * * This report is used by clients to request calendar objects based on * complex conditions. * * @param DOMNode $dom * @return void */ public function calendarQueryReport($dom) { $requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild)); $filterNode = $dom->getElementsByTagNameNS('urn:ietf:params:xml:ns:caldav', 'filter'); if ($filterNode->length !== 1) { throw new Sabre_DAV_Exception_BadRequest('The calendar-query report must have a filter element'); } $filters = Sabre_CalDAV_XMLUtil::parseCalendarQueryFilters($filterNode->item(0)); $requestedCalendarData = true; if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) { // We always retrieve calendar-data, as we need it for filtering. $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data'; // If calendar-data wasn't explicitly requested, we need to remove // it after processing. $requestedCalendarData = false; } // These are the list of nodes that potentially match the requirement $candidateNodes = $this->server->getPropertiesForPath($this->server->getRequestUri(), $requestedProperties, $this->server->getHTTPDepth(0)); $verifiedNodes = array(); foreach ($candidateNodes as $node) { // If the node didn't have a calendar-data property, it must not be a calendar object if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) { continue; } if ($this->validateFilters($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'], $filters)) { if (!$requestedCalendarData) { unset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); } $verifiedNodes[] = $node; } } $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->sendBody($this->server->generateMultiStatus($verifiedNodes)); }
/** * @depends testParamFilter */ function testUndefinedNegation() { $xml = <<<XML <?xml version="1.0"?> <C:filter xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"> <C:comp-filter name="VCALENDAR"> <C:comp-filter name="VTODO"> <C:prop-filter name="COMPLETED"> <C:is-not-defined /> </C:prop-filter> <C:prop-filter name="STATUS"> <C:text-match negate-condition="yes">CANCELLED</C:text-match> </C:prop-filter> </C:comp-filter> </C:comp-filter> </C:filter> XML; $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml); $expected = array('/c:iCalendar/c:vcalendar' => array(), '/c:iCalendar/c:vcalendar/c:vtodo' => array(), '/c:iCalendar/c:vcalendar/c:vtodo/c:completed' => array('is-not-defined' => true), '/c:iCalendar/c:vcalendar/c:vtodo/c:status' => array('text-match' => array('collation' => 'i;ascii-casemap', 'negate-condition' => true, 'value' => 'CANCELLED'))); $result = Sabre_CalDAV_XMLUtil::parseCalendarQueryFilters($dom->firstChild); $this->assertEquals($expected, $result); }