1<?php
2
3namespace Sabre\CalDAV\Xml\Request;
4
5use Sabre\CalDAV\Plugin;
6use Sabre\DAV\Exception\BadRequest;
7use Sabre\Xml\Reader;
8use Sabre\Xml\XmlDeserializable;
9
10/**
11 * CalendarQueryReport request parser.
12 *
13 * This class parses the {urn:ietf:params:xml:ns:caldav}calendar-query
14 * REPORT, as defined in:
15 *
16 * https://tools.ietf.org/html/rfc4791#section-7.9
17 *
18 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
19 * @author Evert Pot (http://www.rooftopsolutions.nl/)
20 * @license http://sabre.io/license/ Modified BSD License
21 */
22class CalendarQueryReport implements XmlDeserializable {
23
24    /**
25     * An array with requested properties.
26     *
27     * @var array
28     */
29    public $properties;
30
31    /**
32     * List of property/component filters.
33     *
34     * @var array
35     */
36    public $filters;
37
38    /**
39     * If the calendar data must be expanded, this will contain an array with 2
40     * elements: start and end.
41     *
42     * Each may be a DateTime or null.
43     *
44     * @var array|null
45     */
46    public $expand = null;
47
48    /**
49     * The mimetype of the content that should be returend. Usually
50     * text/calendar.
51     *
52     * @var string
53     */
54    public $contentType = null;
55
56    /**
57     * The version of calendar-data that should be returned. Usually '2.0',
58     * referring to iCalendar 2.0.
59     *
60     * @var string
61     */
62    public $version = null;
63
64    /**
65     * The deserialize method is called during xml parsing.
66     *
67     * This method is called statically, this is because in theory this method
68     * may be used as a type of constructor, or factory method.
69     *
70     * Often you want to return an instance of the current class, but you are
71     * free to return other data as well.
72     *
73     * You are responsible for advancing the reader to the next element. Not
74     * doing anything will result in a never-ending loop.
75     *
76     * If you just want to skip parsing for this element altogether, you can
77     * just call $reader->next();
78     *
79     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
80     * the next element.
81     *
82     * @param Reader $reader
83     * @return mixed
84     */
85    static function xmlDeserialize(Reader $reader) {
86
87        $elems = $reader->parseInnerTree([
88            '{urn:ietf:params:xml:ns:caldav}comp-filter'   => 'Sabre\\CalDAV\\Xml\\Filter\\CompFilter',
89            '{urn:ietf:params:xml:ns:caldav}prop-filter'   => 'Sabre\\CalDAV\\Xml\\Filter\\PropFilter',
90            '{urn:ietf:params:xml:ns:caldav}param-filter'  => 'Sabre\\CalDAV\\Xml\\Filter\\ParamFilter',
91            '{urn:ietf:params:xml:ns:caldav}calendar-data' => 'Sabre\\CalDAV\\Xml\\Filter\\CalendarData',
92            '{DAV:}prop'                                   => 'Sabre\\Xml\\Element\\KeyValue',
93        ]);
94
95        $newProps = [
96            'filters'    => null,
97            'properties' => [],
98        ];
99
100        if (!is_array($elems)) $elems = [];
101
102        foreach ($elems as $elem) {
103
104            switch ($elem['name']) {
105
106                case '{DAV:}prop' :
107                    $newProps['properties'] = array_keys($elem['value']);
108                    if (isset($elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data'])) {
109                        $newProps += $elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data'];
110                    }
111                    break;
112                case '{' . Plugin::NS_CALDAV . '}filter' :
113                    foreach ($elem['value'] as $subElem) {
114                        if ($subElem['name'] === '{' . Plugin::NS_CALDAV . '}comp-filter') {
115                            if (!is_null($newProps['filters'])) {
116                                throw new BadRequest('Only one top-level comp-filter may be defined');
117                            }
118                            $newProps['filters'] = $subElem['value'];
119                        }
120                    }
121                    break;
122
123            }
124
125        }
126
127        if (is_null($newProps['filters'])) {
128            throw new BadRequest('The {' . Plugin::NS_CALDAV . '}filter element is required for this request');
129        }
130
131        $obj = new self();
132        foreach ($newProps as $key => $value) {
133            $obj->$key = $value;
134        }
135        return $obj;
136
137    }
138
139}
140