1<?php
2
3namespace Sabre\VObject\Component;
4
5use Sabre\VObject;
6
7/**
8 * VTodo component
9 *
10 * This component contains some additional functionality specific for VTODOs.
11 *
12 * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/).
13 * @author Evert Pot (http://evertpot.com/)
14 * @license http://sabre.io/license/ Modified BSD License
15 */
16class VTodo extends VObject\Component {
17
18    /**
19     * Returns true or false depending on if the event falls in the specified
20     * time-range. This is used for filtering purposes.
21     *
22     * The rules used to determine if an event falls within the specified
23     * time-range is based on the CalDAV specification.
24     *
25     * @param DateTime $start
26     * @param DateTime $end
27     * @return bool
28     */
29    public function isInTimeRange(\DateTime $start, \DateTime $end) {
30
31        $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
32        $duration = isset($this->DURATION)?VObject\DateTimeParser::parseDuration($this->DURATION):null;
33        $due = isset($this->DUE)?$this->DUE->getDateTime():null;
34        $completed = isset($this->COMPLETED)?$this->COMPLETED->getDateTime():null;
35        $created = isset($this->CREATED)?$this->CREATED->getDateTime():null;
36
37        if ($dtstart) {
38            if ($duration) {
39                $effectiveEnd = clone $dtstart;
40                $effectiveEnd->add($duration);
41                return $start <= $effectiveEnd && $end > $dtstart;
42            } elseif ($due) {
43                return
44                    ($start < $due || $start <= $dtstart) &&
45                    ($end > $dtstart || $end >= $due);
46            } else {
47                return $start <= $dtstart && $end > $dtstart;
48            }
49        }
50        if ($due) {
51            return ($start < $due && $end >= $due);
52        }
53        if ($completed && $created) {
54            return
55                ($start <= $created || $start <= $completed) &&
56                ($end >= $created || $end >= $completed);
57        }
58        if ($completed) {
59            return ($start <= $completed && $end >= $completed);
60        }
61        if ($created) {
62            return ($end > $created);
63        }
64        return true;
65
66    }
67
68    /**
69     * A simple list of validation rules.
70     *
71     * This is simply a list of properties, and how many times they either
72     * must or must not appear.
73     *
74     * Possible values per property:
75     *   * 0 - Must not appear.
76     *   * 1 - Must appear exactly once.
77     *   * + - Must appear at least once.
78     *   * * - Can appear any number of times.
79     *   * ? - May appear, but not more than once.
80     *
81     * @var array
82     */
83    public function getValidationRules() {
84
85        return array(
86            'UID' => 1,
87            'DTSTAMP' => 1,
88
89            'CLASS' => '?',
90            'COMPLETED' => '?',
91            'CREATED' => '?',
92            'DESCRIPTION' => '?',
93            'DTSTART' => '?',
94            'GEO' => '?',
95            'LAST-MODIFIED' => '?',
96            'LOCATION' => '?',
97            'ORGANIZER' => '?',
98            'PERCENT' => '?',
99            'PRIORITY' => '?',
100            'RECURRENCE-ID' => '?',
101            'SEQUENCE' => '?',
102            'STATUS' => '?',
103            'SUMMARY' => '?',
104            'URL' => '?',
105
106            'RRULE' => '?',
107            'DUE' => '?',
108            'DURATION' => '?',
109
110            'ATTACH' => '*',
111            'ATTENDEE' => '*',
112            'CATEGORIES' => '*',
113            'COMMENT' => '*',
114            'CONTACT' => '*',
115            'EXDATE' => '*',
116            'REQUEST-STATUS' => '*',
117            'RELATED-TO' => '*',
118            'RESOURCES' => '*',
119            'RDATE' => '*',
120        );
121
122    }
123
124    /**
125     * Validates the node for correctness.
126     *
127     * The following options are supported:
128     *   Node::REPAIR - May attempt to automatically repair the problem.
129     *
130     * This method returns an array with detected problems.
131     * Every element has the following properties:
132     *
133     *  * level - problem level.
134     *  * message - A human-readable string describing the issue.
135     *  * node - A reference to the problematic node.
136     *
137     * The level means:
138     *   1 - The issue was repaired (only happens if REPAIR was turned on)
139     *   2 - An inconsequential issue
140     *   3 - A severe issue.
141     *
142     * @param int $options
143     * @return array
144     */
145    public function validate($options = 0) {
146
147        $result = parent::validate($options);
148        if (isset($this->DUE) && isset($this->DTSTART)) {
149
150            $due = $this->DUE;
151            $dtStart = $this->DTSTART;
152
153            if ($due->getValueType() !== $dtStart->getValueType()) {
154
155                $result[] = array(
156                    'level'   => 3,
157                    'message' => 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART',
158                    'node' => $due,
159                );
160
161            } elseif ($due->getDateTime() < $dtStart->getDateTime()) {
162
163                $result[] = array(
164                    'level'   => 3,
165                    'message' => 'DUE must occur after DTSTART',
166                    'node' => $due,
167                );
168
169            }
170
171        }
172
173        return $result;
174
175    }
176
177}
178