123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- <?php
- /**
- * Parses the addressbook-query report request body.
- *
- * Whoever designed this format, and the CalDAV equavalent even more so,
- * has no feel for design.
- *
- * @package Sabre
- * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
- class Sabre_CardDAV_AddressBookQueryParser {
- const TEST_ANYOF = 'anyof';
- const TEST_ALLOF = 'allof';
- /**
- * List of requested properties the client wanted
- *
- * @var array
- */
- public $requestedProperties;
- /**
- * The number of results the client wants
- *
- * null means it wasn't specified, which in most cases means 'all results'.
- *
- * @var int|null
- */
- public $limit;
- /**
- * List of property filters.
- *
- * @var array
- */
- public $filters;
- /**
- * Either TEST_ANYOF or TEST_ALLOF
- *
- * @var string
- */
- public $test;
- /**
- * DOM Document
- *
- * @var DOMDocument
- */
- protected $dom;
- /**
- * DOM XPath object
- *
- * @var DOMXPath
- */
- protected $xpath;
- /**
- * Creates the parser
- *
- * @param DOMNode $dom
- * @return void
- */
- public function __construct(DOMDocument $dom) {
- $this->dom = $dom;
- $this->xpath = new DOMXPath($dom);
- $this->xpath->registerNameSpace('card',Sabre_CardDAV_Plugin::NS_CARDDAV);
- }
- /**
- * Parses the request.
- *
- * @param DOMNode $dom
- * @return void
- */
- public function parse() {
- $filterNode = null;
-
- $limit = $this->xpath->evaluate('number(/card:addressbook-query/card:limit/card:nresults)');
- if (is_nan($limit)) $limit = null;
- $filter = $this->xpath->query('/card:addressbook-query/card:filter');
- if ($filter->length !== 1) {
- throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
- }
- $filter = $filter->item(0);
- $test = $this->xpath->evaluate('string(@test)', $filter);
- if (!$test) $test = self::TEST_ANYOF;
- if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) {
- throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"');
- }
- $propFilters = array();
- $propFilterNodes = $this->xpath->query('card:prop-filter', $filter);
- for($ii=0; $ii < $propFilterNodes->length; $ii++) {
- $propFilters[] = $this->parsePropFilterNode($propFilterNodes->item($ii));
- }
- $this->filters = $propFilters;
- $this->limit = $limit;
- $this->requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($this->dom->firstChild));
- $this->test = $test;
- }
- /**
- * Parses the prop-filter xml element
- *
- * @param DOMElement $propFilterNode
- * @return array
- */
- protected function parsePropFilterNode(DOMElement $propFilterNode) {
- $propFilter = array();
- $propFilter['name'] = $propFilterNode->getAttribute('name');
- $propFilter['test'] = $propFilterNode->getAttribute('test');
- if (!$propFilter['test']) $propFilter['test'] = 'anyof';
- $propFilter['is-not-defined'] = $this->xpath->query('card:is-not-defined', $propFilterNode)->length>0;
- $paramFilterNodes = $this->xpath->query('card:param-filter', $propFilterNode);
- $propFilter['param-filters'] = array();
- for($ii=0;$ii<$paramFilterNodes->length;$ii++) {
- $propFilter['param-filters'][] = $this->parseParamFilterNode($paramFilterNodes->item($ii));
- }
- $propFilter['text-matches'] = array();
- $textMatchNodes = $this->xpath->query('card:text-match', $propFilterNode);
- for($ii=0;$ii<$textMatchNodes->length;$ii++) {
- $propFilter['text-matches'][] = $this->parseTextMatchNode($textMatchNodes->item($ii));
- }
- return $propFilter;
- }
- /**
- * Parses the param-filter element
- *
- * @param DOMElement $paramFilterNode
- * @return array
- */
- public function parseParamFilterNode(DOMElement $paramFilterNode) {
-
- $paramFilter = array();
- $paramFilter['name'] = $paramFilterNode->getAttribute('name');
- $paramFilter['is-not-defined'] = $this->xpath->query('card:is-not-defined', $paramFilterNode)->length>0;
- $paramFilter['text-match'] = null;
- $textMatch = $this->xpath->query('card:text-match', $paramFilterNode);
- if ($textMatch->length>0) {
- $paramFilter['text-match'] = $this->parseTextMatchNode($textMatch->item(0));
- }
- return $paramFilter;
- }
- /**
- * Text match
- *
- * @param DOMElement $textMatchNode
- * @return void
- */
- public function parseTextMatchNode(DOMElement $textMatchNode) {
- $matchType = $textMatchNode->getAttribute('match-type');
- if (!$matchType) $matchType = 'contains';
- if (!in_array($matchType, array('contains', 'equals', 'starts-with', 'ends-with'))) {
- throw new Sabre_DAV_Exception_BadRequest('Unknown match-type: ' . $matchType);
- }
- $negateCondition = $textMatchNode->getAttribute('negate-condition');
- $negateCondition = $negateCondition==='yes';
- $collation = $textMatchNode->getAttribute('collation');
- if (!$collation) $collation = 'i;unicode-casemap';
- return array(
- 'negate-condition' => $negateCondition,
- 'collation' => $collation,
- 'match-type' => $matchType,
- 'value' => $textMatchNode->nodeValue
- );
-
- }
- }
|