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