3 abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract
8 protected $propertyMap = array(
9 '{DAV:}displayname' => 'displayname',
10 '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description',
11 '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone',
12 '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
13 '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
21 abstract public function getNamespace();
28 abstract public static function getBackendTypeName();
32 * @param int $calendarId
35 * @param string $base_path
38 abstract public function listItemsByRange($calendarId, $sd, $ed, $base_path);
44 static private $calendarCache = array();
49 static private $calendarObjectCache = array();
53 * @param int $calendarId
56 static public function loadCalendarById($calendarId)
58 if (!isset(self::$calendarCache[$calendarId])) {
59 $c = q("SELECT * FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
60 self::$calendarCache[$calendarId] = $c[0];
62 return self::$calendarCache[$calendarId];
70 static public function loadCalendarobjectById($obj_id)
72 if (!isset(self::$calendarObjectCache[$obj_id])) {
73 $o = q("SELECT * FROM %s%scalendarobjects WHERE `id` = %d",
74 CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($obj_id)
76 self::$calendarObjectCache[$obj_id] = $o[0];
78 return self::$calendarObjectCache[$obj_id];
84 * @param Sabre\VObject\Component\VEvent $component
87 public static function getDtEndTimeStamp(&$component)
89 /** @var Sabre\VObject\Property\DateTime $dtstart */
90 $dtstart = $component->__get("DTSTART");
91 if ($component->__get("DTEND")) {
92 /** @var Sabre\VObject\Property\DateTime $dtend */
93 $dtend = $component->__get("DTEND");
94 return $dtend->getDateTime()->getTimeStamp();
95 } elseif ($component->__get("DURATION")) {
96 $endDate = clone $dtstart->getDateTime();
97 $endDate->add(Sabre\VObject\DateTimeParser::parse($component->__get("DURATION")->value));
98 return $endDate->getTimeStamp();
99 } elseif ($dtstart->getDateType() === Sabre\VObject\Property\DateTime::DATE) {
100 $endDate = clone $dtstart->getDateTime();
101 $endDate->modify('+1 day');
102 return $endDate->getTimeStamp();
104 return $dtstart->getDateTime()->getTimeStamp() + 3600;
111 * Parses some information from calendar objects, used for optimized
114 * Returns an array with the following keys:
121 * @param string $calendarData
122 * @throws Sabre_DAV_Exception_BadRequest
125 protected function getDenormalizedData($calendarData)
127 /** @var Sabre\VObject\Component\VEvent $vObject */
128 $vObject = Sabre\VObject\Reader::read($calendarData);
129 $componentType = null;
131 $firstOccurence = null;
132 $lastOccurence = null;
134 foreach ($vObject->getComponents() as $component) {
135 if ($component->name !== 'VTIMEZONE') {
136 $componentType = $component->name;
140 if (!$componentType) {
141 throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
143 if ($componentType === 'VEVENT') {
144 /** @var Sabre\VObject\Component\VEvent $component */
145 /** @var Sabre\VObject\Property\DateTime $dtstart */
146 $dtstart = $component->__get("DTSTART");
147 $firstOccurence = $dtstart->getDateTime()->getTimeStamp();
148 // Finding the last occurence is a bit harder
149 if (!$component->__get("RRULE")) {
150 $lastOccurence = self::getDtEndTimeStamp($component);
152 $it = new Sabre\VObject\RecurrenceIterator($vObject, (string)$component->__get("UID"));
153 $maxDate = new DateTime(CALDAV_MAX_YEAR . "-01-01");
154 if ($it->isInfinite()) {
155 $lastOccurence = $maxDate->getTimeStamp();
157 $end = $it->getDtEnd();
158 while ($it->valid() && $end < $maxDate) {
159 $end = $it->getDtEnd();
163 $lastOccurence = $end->getTimeStamp();
170 'etag' => md5($calendarData),
171 'size' => strlen($calendarData),
172 'componentType' => $componentType,
173 'firstOccurence' => $firstOccurence,
174 'lastOccurence' => $lastOccurence,
180 * Updates properties for a calendar.
182 * The mutations array uses the propertyName in clark-notation as key,
183 * and the array value for the property value. In the case a property
184 * should be deleted, the property value will be null.
186 * This method must be atomic. If one property cannot be changed, the
187 * entire operation must fail.
189 * If the operation was successful, true can be returned.
190 * If the operation failed, false can be returned.
192 * Deletion of a non-existent property is always successful.
194 * Lastly, it is optional to return detailed information about any
195 * failures. In this case an array should be returned with the following
200 * '{DAV:}displayname' => null,
203 * '{DAV:}owner' => null,
207 * In this example it was forbidden to update {DAV:}displayname.
208 * (403 Forbidden), which in turn also caused {DAV:}owner to fail
209 * (424 Failed Dependency) because the request needs to be atomic.
211 * @param mixed $calendarId
212 * @param array $mutations
215 public function updateCalendar($calendarId, array $mutations)
218 $newValues = array();
220 200 => array(), // Ok
221 403 => array(), // Forbidden
222 424 => array(), // Failed Dependency
227 foreach ($mutations as $propertyName=> $propertyValue) {
229 // We don't know about this property.
230 if (!isset($this->propertyMap[$propertyName])) {
232 $result[403][$propertyName] = null;
233 unset($mutations[$propertyName]);
237 $fieldName = $this->propertyMap[$propertyName];
238 $newValues[$fieldName] = $propertyValue;
242 // If there were any errors we need to fail the request
244 // Properties has the remaining properties
245 foreach ($mutations as $propertyName=> $propertyValue) {
246 $result[424][$propertyName] = null;
249 // Removing unused statuscodes for cleanliness
250 foreach ($result as $status=> $properties) {
251 if (is_array($properties) && count($properties) === 0) unset($result[$status]);
258 $this->increaseCalendarCtag($calendarId);
260 $valuesSql = array();
261 foreach ($newValues as $fieldName=> $value) $valuesSql[] = "`" . $fieldName . "` = '" . dbesc($value) . "'";
262 if (count($valuesSql) > 0) {
263 q("UPDATE %s%scalendars SET " . implode(", ", $valuesSql) . " WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
271 * @param int $calendarId
273 protected function increaseCalendarCtag($calendarId)
275 q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 WHERE `id` = '%d'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
276 self::$calendarObjectCache = array();
281 * @param int $calendar_id
282 * @param int $calendarobject_id
285 abstract function getItemDetailRedirect($calendar_id, $calendarobject_id);