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();
25 * @param int $calendarId
28 * @param string $base_path
31 abstract public function listItemsByRange($calendarId, $sd, $ed, $base_path);
37 static private $calendarCache = array();
42 static private $calendarObjectCache = array();
46 * @param int $calendarId
49 static public function loadCalendarById($calendarId)
51 if (!isset(self::$calendarCache[$calendarId])) {
52 $c = q("SELECT * FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
53 self::$calendarCache[$calendarId] = $c[0];
55 return self::$calendarCache[$calendarId];
63 static public function loadCalendarobjectById($obj_id)
65 if (!isset(self::$calendarObjectCache[$obj_id])) {
66 $o = q("SELECT * FROM %s%scalendarobjects WHERE `id` = %d",
67 CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($obj_id)
69 self::$calendarObjectCache[$obj_id] = $o[0];
71 return self::$calendarObjectCache[$obj_id];
77 * @param Sabre_VObject_Component_VEvent $component
80 public static function getDtEndTimeStamp(&$component)
82 /** @var Sabre_VObject_Property_DateTime $dtstart */
83 $dtstart = $component->__get("DTSTART");
84 if ($component->__get("DTEND")) {
85 /** @var Sabre_VObject_Property_DateTime $dtend */
86 $dtend = $component->__get("DTEND");
87 return $dtend->getDateTime()->getTimeStamp();
88 } elseif ($component->__get("DURATION")) {
89 $endDate = clone $dtstart->getDateTime();
90 $endDate->add(Sabre_VObject_DateTimeParser::parse($component->__get("DURATION")->value));
91 return $endDate->getTimeStamp();
92 } elseif ($dtstart->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
93 $endDate = clone $dtstart->getDateTime();
94 $endDate->modify('+1 day');
95 return $endDate->getTimeStamp();
97 return $dtstart->getDateTime()->getTimeStamp() + 3600;
104 * Parses some information from calendar objects, used for optimized
107 * Returns an array with the following keys:
114 * @param string $calendarData
115 * @throws Sabre_DAV_Exception_BadRequest
118 protected function getDenormalizedData($calendarData)
120 /** @var Sabre_VObject_Component_VEvent $vObject */
121 $vObject = Sabre_VObject_Reader::read($calendarData);
122 $componentType = null;
124 $firstOccurence = null;
125 $lastOccurence = null;
126 foreach ($vObject->getComponents() as $component) {
127 if ($component->name !== 'VTIMEZONE') {
128 $componentType = $component->name;
132 if (!$componentType) {
133 throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
135 if ($componentType === 'VEVENT') {
136 /** @var Sabre_VObject_Component_VEvent $component */
137 /** @var Sabre_VObject_Property_DateTime $dtstart */
138 $dtstart = $component->__get("DTSTART");
139 $firstOccurence = $dtstart->getDateTime()->getTimeStamp();
140 // Finding the last occurence is a bit harder
141 if (!$component->__get("RRULE")) {
142 $lastOccurence = self::getDtEndTimeStamp($component);
144 $it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->__get("UID"));
145 $maxDate = new DateTime(CALDAV_MAX_YEAR . "-01-01");
146 if ($it->isInfinite()) {
147 $lastOccurence = $maxDate->getTimeStamp();
149 $end = $it->getDtEnd();
150 while ($it->valid() && $end < $maxDate) {
151 $end = $it->getDtEnd();
155 $lastOccurence = $end->getTimeStamp();
162 'etag' => md5($calendarData),
163 'size' => strlen($calendarData),
164 'componentType' => $componentType,
165 'firstOccurence' => $firstOccurence,
166 'lastOccurence' => $lastOccurence,
172 * Updates properties for a calendar.
174 * The mutations array uses the propertyName in clark-notation as key,
175 * and the array value for the property value. In the case a property
176 * should be deleted, the property value will be null.
178 * This method must be atomic. If one property cannot be changed, the
179 * entire operation must fail.
181 * If the operation was successful, true can be returned.
182 * If the operation failed, false can be returned.
184 * Deletion of a non-existent property is always successful.
186 * Lastly, it is optional to return detailed information about any
187 * failures. In this case an array should be returned with the following
192 * '{DAV:}displayname' => null,
195 * '{DAV:}owner' => null,
199 * In this example it was forbidden to update {DAV:}displayname.
200 * (403 Forbidden), which in turn also caused {DAV:}owner to fail
201 * (424 Failed Dependency) because the request needs to be atomic.
203 * @param mixed $calendarId
204 * @param array $mutations
207 public function updateCalendar($calendarId, array $mutations)
210 $newValues = array();
212 200 => array(), // Ok
213 403 => array(), // Forbidden
214 424 => array(), // Failed Dependency
219 foreach ($mutations as $propertyName=> $propertyValue) {
221 // We don't know about this property.
222 if (!isset($this->propertyMap[$propertyName])) {
224 $result[403][$propertyName] = null;
225 unset($mutations[$propertyName]);
229 $fieldName = $this->propertyMap[$propertyName];
230 $newValues[$fieldName] = $propertyValue;
234 // If there were any errors we need to fail the request
236 // Properties has the remaining properties
237 foreach ($mutations as $propertyName=> $propertyValue) {
238 $result[424][$propertyName] = null;
241 // Removing unused statuscodes for cleanliness
242 foreach ($result as $status=> $properties) {
243 if (is_array($properties) && count($properties) === 0) unset($result[$status]);
250 $this->increaseCalendarCtag($calendarId);
252 $valuesSql = array();
253 foreach ($newValues as $fieldName=> $value) $valuesSql[] = "`" . $fieldName . "` = '" . dbesc($value) . "'";
254 if (count($valuesSql) > 0) {
255 q("UPDATE %s%scalendars SET " . implode(", ", $valuesSql) . " WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
263 * @param int $calendarId
265 protected function increaseCalendarCtag($calendarId)
267 q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 WHERE `id` = '%d'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
268 self::$calendarObjectCache = array();
273 * @param int $calendar_id
274 * @param int $calendarobject_id
277 abstract function getItemDetailRedirect($calendar_id, $calendarobject_id);