예제 #1
0
 /**
  * Sends one or more iTip messages through email.
  * 
  * @param string $originator 
  * @param array $recipients 
  * @param Sabre_VObject_Component $vObject 
  * @return void
  */
 public function sendMessage($originator, array $recipients, Sabre_VObject_Component $vObject)
 {
     foreach ($recipients as $recipient) {
         $to = $recipient;
         $replyTo = $originator;
         $subject = 'SabreDAV iTIP message';
         switch (strtoupper($vObject->METHOD)) {
             case 'REPLY':
                 $subject = 'Response for: ' . $vObject->VEVENT->SUMMARY;
                 break;
             case 'REQUEST':
                 $subject = 'Invitation for: ' . $vObject->VEVENT->SUMMARY;
                 break;
             case 'CANCEL':
                 $subject = 'Cancelled event: ' . $vObject->VEVENT->SUMMARY;
                 break;
         }
         $headers = array();
         $headers[] = 'Reply-To: ' . $replyTo;
         $headers[] = 'From: ' . $this->senderEmail;
         $headers[] = 'Content-Type: text/calendar; method=' . (string) $vObject->method . '; charset=utf-8';
         $headers[] = 'X-Sabre-Version: ' . Sabre_DAV_Version::VERSION . '-' . Sabre_DAV_Version::STABILITY;
         $vcalBody = $vObject->serialize();
         $this->mail($to, $subject, $vcalBody, $headers);
     }
 }
예제 #2
0
 function testStuff()
 {
     $vcard = new Sabre_VObject_Component('VCARD');
     $vcard->VERSION = '3.0';
     $vcard->UID = 'foo-bar';
     $vcard->PHOTO = base64_encode('random_stuff');
     $vcard->PHOTO->add('BASE64', null);
     $result = $vcard->serialize();
     $expected = array("BEGIN:VCARD", "VERSION:3.0", "PHOTO;BASE64:" . base64_encode('random_stuff'), "UID:foo-bar", "END:VCARD", "");
     $this->assertEquals(implode("\r\n", $expected), $result);
 }
예제 #3
0
 /**
  * Reads and parses a single line.
  *
  * This method receives the full array of lines. The array pointer is used
  * to traverse.
  * 
  * @param array $lines 
  * @return Sabre_VObject_Element 
  */
 private static function readLine(&$lines)
 {
     $line = current($lines);
     $lineNr = key($lines);
     next($lines);
     // Components
     if (stripos($line, "BEGIN:") === 0) {
         // This is a component
         $obj = new Sabre_VObject_Component(strtoupper(substr($line, 6)));
         $nextLine = current($lines);
         while (stripos($nextLine, "END:") !== 0) {
             $obj->add(self::readLine($lines));
             $nextLine = current($lines);
             if ($nextLine === false) {
                 throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.');
             }
         }
         // Checking component name of the 'END:' line.
         if (substr($nextLine, 4) !== $obj->name) {
             throw new Sabre_VObject_ParseException('Invalid VObject, expected: "END:' . $obj->name . '" got: "' . $nextLine . '"');
         }
         next($lines);
         return $obj;
     }
     // Properties
     //$result = preg_match('/(?P<name>[A-Z0-9-]+)(?:;(?P<parameters>^(?<!:):))(.*)$/',$line,$matches);
     $token = '[A-Z0-9-\\.]+';
     $parameters = "(?:;(?P<parameters>([^:^\"]|\"([^\"]*)\")*))?";
     $regex = "/^(?P<name>{$token}){$parameters}:(?P<value>.*)\$/i";
     $result = preg_match($regex, $line, $matches);
     if (!$result) {
         throw new Sabre_VObject_ParseException('Invalid VObject, line ' . ($lineNr + 1) . ' did not follow the icalendar/vcard format');
     }
     $propertyName = strtoupper($matches['name']);
     if (strpos($propertyName, '.') !== false) {
         list(, $mapName) = explode('.', $propertyName);
     } else {
         $mapName = $propertyName;
     }
     if (isset(self::$elementMap[$mapName])) {
         $className = self::$elementMap[$mapName];
     } else {
         $className = 'Sabre_VObject_Property';
     }
     $propertyValue = $className::stripSlashes($matches['value']);
     $obj = new $className($propertyName, $propertyValue);
     if ($matches['parameters']) {
         foreach (self::readParameters($matches['parameters']) as $param) {
             $obj->add($param);
         }
     }
     return $obj;
 }
 /**
  * Different bug, also likely an infinite loop.
  */
 function testYearlyByMonthLoop()
 {
     $ev = Sabre_VObject_Component::create('VEVENT');
     $ev->UID = 'uuid';
     $ev->DTSTART = '20120101T154500';
     $ev->DTSTART['TZID'] = 'Europe/Berlin';
     $ev->RRULE = 'FREQ=YEARLY;INTERVAL=1;UNTIL=20120203T225959Z;BYMONTH=2;BYSETPOS=1;BYDAY=SU,MO,TU,WE,TH,FR,SA';
     $ev->DTEND = '20120101T164500';
     $ev->DTEND['TZID'] = 'Europe/Berlin';
     // This recurrence rule by itself is a yearly rule that should happen
     // every february.
     //
     // The BYDAY part expands this to every day of the month, but the
     // BYSETPOS limits this to only the 1st day of the month. Very crazy
     // way to specify this, and could have certainly been a lot easier.
     $cal = Sabre_VObject_Component::create('VCALENDAR');
     $cal->add($ev);
     $it = new Sabre_VObject_RecurrenceIterator($cal, 'uuid');
     $it->fastForward(new DateTime('2012-01-29 23:00:00', new DateTimeZone('UTC')));
     $collect = array();
     while ($it->valid()) {
         $collect[] = $it->getDTSTART();
         if ($it->getDTSTART() > new DateTime('2013-02-05 22:59:59', new DateTimeZone('UTC'))) {
             break;
         }
         $it->next();
     }
     $this->assertEquals(array(new DateTime('2012-02-01 15:45:00', new DateTimeZone('Europe/Berlin'))), $collect);
 }
 function testAlarmWayBefore()
 {
     $vevent = Sabre_VObject_Component::create('VEVENT');
     $vevent->DTSTART = '20120101T120000Z';
     $vevent->UID = 'bla';
     $valarm = Sabre_VObject_Component::create('VALARM');
     $valarm->TRIGGER = '-P2W1D';
     $vevent->add($valarm);
     $vcalendar = Sabre_VObject_Component::create('VCALENDAR');
     $vcalendar->add($vevent);
     $filter = array('name' => 'VCALENDAR', 'is-not-defined' => false, 'time-range' => null, 'prop-filters' => array(), 'comp-filters' => array(array('name' => 'VEVENT', 'is-not-defined' => false, 'time-range' => null, 'prop-filters' => array(), 'comp-filters' => array(array('name' => 'VALARM', 'is-not-defined' => false, 'prop-filters' => array(), 'comp-filters' => array(), 'time-range' => array('start' => new DateTime('2011-12-10'), 'end' => new DateTime('2011-12-20')))))));
     $validator = new Sabre_CalDAV_CalendarQueryValidator();
     $this->assertTrue($validator->validate($vcalendar, $filter));
 }
예제 #6
0
 /**
  * Reads and parses a single line.
  *
  * This method receives the full array of lines. The array pointer is used
  * to traverse.
  *
  * @param array $lines
  * @return Sabre_VObject_Element
  */
 private static function readLine(&$lines)
 {
     $line = current($lines);
     $lineNr = key($lines);
     next($lines);
     // Components
     if (stripos($line, "BEGIN:") === 0) {
         $componentName = strtoupper(substr($line, 6));
         $obj = Sabre_VObject_Component::create($componentName);
         $nextLine = current($lines);
         while (stripos($nextLine, "END:") !== 0) {
             $obj->add(self::readLine($lines));
             $nextLine = current($lines);
             if ($nextLine === false) {
                 throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.');
             }
         }
         // Checking component name of the 'END:' line.
         if (substr($nextLine, 4) !== $obj->name) {
             throw new Sabre_VObject_ParseException('Invalid VObject, expected: "END:' . $obj->name . '" got: "' . $nextLine . '"');
         }
         next($lines);
         return $obj;
     }
     // Properties
     //$result = preg_match('/(?P<name>[A-Z0-9-]+)(?:;(?P<parameters>^(?<!:):))(.*)$/',$line,$matches);
     $token = '[A-Z0-9-\\.]+';
     $parameters = "(?:;(?P<parameters>([^:^\"]|\"([^\"]*)\")*))?";
     $regex = "/^(?P<name>{$token}){$parameters}:(?P<value>.*)\$/i";
     $result = preg_match($regex, $line, $matches);
     if (!$result) {
         throw new Sabre_VObject_ParseException('Invalid VObject, line ' . ($lineNr + 1) . ' did not follow the icalendar/vcard format');
     }
     $propertyName = strtoupper($matches['name']);
     $propertyValue = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#', function ($matches) {
         if ($matches[2] === 'n' || $matches[2] === 'N') {
             return "\n";
         } else {
             return $matches[2];
         }
     }, $matches['value']);
     $obj = Sabre_VObject_Property::create($propertyName, $propertyValue);
     if ($matches['parameters']) {
         foreach (self::readParameters($matches['parameters']) as $param) {
             $obj->add($param);
         }
     }
     return $obj;
 }
예제 #7
0
 /**
  * Merges all calendar objects, and builds one big ics export
  *
  * @param array $nodes
  * @return string
  */
 public function generateICS(array $nodes)
 {
     $calendar = new Sabre_VObject_Component('vcalendar');
     $calendar->version = '2.0';
     if (Sabre_DAV_Server::$exposeVersion) {
         $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
     } else {
         $calendar->prodid = '-//SabreDAV//SabreDAV//EN';
     }
     $calendar->calscale = 'GREGORIAN';
     $collectedTimezones = array();
     $timezones = array();
     $objects = array();
     foreach ($nodes as $node) {
         if (!isset($node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'])) {
             continue;
         }
         $nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'];
         $nodeComp = Sabre_VObject_Reader::read($nodeData);
         foreach ($nodeComp->children() as $child) {
             switch ($child->name) {
                 case 'VEVENT':
                 case 'VTODO':
                 case 'VJOURNAL':
                     $objects[] = $child;
                     break;
                     // VTIMEZONE is special, because we need to filter out the duplicates
                 // VTIMEZONE is special, because we need to filter out the duplicates
                 case 'VTIMEZONE':
                     // Naively just checking tzid.
                     if (in_array((string) $child->TZID, $collectedTimezones)) {
                         continue;
                     }
                     $timezones[] = $child;
                     $collectedTimezones[] = $child->TZID;
                     break;
             }
         }
     }
     foreach ($timezones as $tz) {
         $calendar->add($tz);
     }
     foreach ($objects as $obj) {
         $calendar->add($obj);
     }
     return $calendar->serialize();
 }
예제 #8
0
 public function timeRangeTestData()
 {
     $tests = array();
     $vjournal = Sabre_VObject_Component::create('VJOURNAL');
     $vjournal->DTSTART = '20111223T120000Z';
     $tests[] = array($vjournal, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vjournal, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vjournal2 = Sabre_VObject_Component::create('VJOURNAL');
     $vjournal2->DTSTART = '20111223';
     $vjournal2->DTSTART['VALUE'] = 'DATE';
     $tests[] = array($vjournal2, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vjournal2, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vjournal3 = Sabre_VObject_Component::create('VJOURNAL');
     $tests[] = array($vjournal3, new DateTime('2011-01-01'), new DateTime('2012-01-01'), false);
     $tests[] = array($vjournal3, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     return $tests;
 }
예제 #9
0
 public function timeRangeTestData()
 {
     $tests = array();
     $vtodo = Sabre_VObject_Component::create('VTODO');
     $vtodo->DTSTART = '20111223T120000Z';
     $tests[] = array($vtodo, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo2 = clone $vtodo;
     $vtodo2->DURATION = 'P1D';
     $tests[] = array($vtodo2, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo2, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo3 = clone $vtodo;
     $vtodo3->DUE = '20111225';
     $tests[] = array($vtodo3, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo3, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo4 = Sabre_VObject_Component::create('VTODO');
     $vtodo4->DUE = '20111225';
     $tests[] = array($vtodo4, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo4, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo5 = Sabre_VObject_Component::create('VTODO');
     $vtodo5->COMPLETED = '20111225';
     $tests[] = array($vtodo5, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo5, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo6 = Sabre_VObject_Component::create('VTODO');
     $vtodo6->CREATED = '20111225';
     $tests[] = array($vtodo6, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo6, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo7 = Sabre_VObject_Component::create('VTODO');
     $vtodo7->CREATED = '20111225';
     $vtodo7->COMPLETED = '20111226';
     $tests[] = array($vtodo7, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo7, new DateTime('2011-01-01'), new DateTime('2011-11-01'), false);
     $vtodo7 = Sabre_VObject_Component::create('VTODO');
     $tests[] = array($vtodo7, new DateTime('2011-01-01'), new DateTime('2012-01-01'), true);
     $tests[] = array($vtodo7, new DateTime('2011-01-01'), new DateTime('2011-11-01'), true);
     return $tests;
 }
예제 #10
0
 /**
  * Creates the iterator
  *
  * You should pass a VCALENDAR component, as well as the UID of the event
  * we're going to traverse.
  *
  * @param Sabre_VObject_Component $comp
  */
 public function __construct(Sabre_VObject_Component $vcal, $uid = null)
 {
     if (is_null($uid)) {
         if ($vcal->name === 'VCALENDAR') {
             throw new InvalidArgumentException('If you pass a VCALENDAR object, you must pass a uid argument as well');
         }
         $components = array($vcal);
         $uid = (string) $vcal->uid;
     } else {
         $components = $vcal->select('VEVENT');
     }
     foreach ($components as $component) {
         if ((string) $component->uid == $uid) {
             if (isset($component->{'RECURRENCE-ID'})) {
                 $this->overriddenEvents[$component->DTSTART->getDateTime()->getTimeStamp()] = $component;
                 $this->overriddenDates[] = $component->{'RECURRENCE-ID'}->getDateTime();
             } else {
                 $this->baseEvent = $component;
             }
         }
     }
     if (!$this->baseEvent) {
         throw new InvalidArgumentException('Could not find a base event with uid: ' . $uid);
     }
     $this->startDate = clone $this->baseEvent->DTSTART->getDateTime();
     $this->endDate = null;
     if (isset($this->baseEvent->DTEND)) {
         $this->endDate = clone $this->baseEvent->DTEND->getDateTime();
     } else {
         $this->endDate = clone $this->startDate;
         if (isset($this->baseEvent->DURATION)) {
             $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value));
         }
     }
     $this->currentDate = clone $this->startDate;
     $rrule = (string) $this->baseEvent->RRULE;
     $parts = explode(';', $rrule);
     foreach ($parts as $part) {
         list($key, $value) = explode('=', $part, 2);
         switch (strtoupper($key)) {
             case 'FREQ':
                 if (!in_array(strtolower($value), array('secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'))) {
                     throw new InvalidArgumentException('Unknown value for FREQ=' . strtoupper($value));
                 }
                 $this->frequency = strtolower($value);
                 break;
             case 'UNTIL':
                 $this->until = Sabre_VObject_DateTimeParser::parse($value);
                 break;
             case 'COUNT':
                 $this->count = (int) $value;
                 break;
             case 'INTERVAL':
                 $this->interval = (int) $value;
                 break;
             case 'BYSECOND':
                 $this->bySecond = explode(',', $value);
                 break;
             case 'BYMINUTE':
                 $this->byMinute = explode(',', $value);
                 break;
             case 'BYHOUR':
                 $this->byHour = explode(',', $value);
                 break;
             case 'BYDAY':
                 $this->byDay = explode(',', strtoupper($value));
                 break;
             case 'BYMONTHDAY':
                 $this->byMonthDay = explode(',', $value);
                 break;
             case 'BYYEARDAY':
                 $this->byYearDay = explode(',', $value);
                 break;
             case 'BYWEEKNO':
                 $this->byWeekNo = explode(',', $value);
                 break;
             case 'BYMONTH':
                 $this->byMonth = explode(',', $value);
                 break;
             case 'BYSETPOS':
                 $this->bySetPos = explode(',', $value);
                 break;
             case 'WKST':
                 $this->weekStart = strtoupper($value);
                 break;
         }
     }
     // Parsing exception dates
     if (isset($this->baseEvent->EXDATE)) {
         foreach ($this->baseEvent->EXDATE as $exDate) {
             foreach (explode(',', (string) $exDate) as $exceptionDate) {
                 $this->exceptionDates[] = Sabre_VObject_DateTimeParser::parse($exceptionDate, $this->startDate->getTimeZone());
             }
         }
     }
 }
예제 #11
0
 /**
  * Parses the input data and returns a correct VFREEBUSY object, wrapped in
  * a VCALENDAR.
  *
  * @return Sabre_VObject_Component
  */
 public function getResult()
 {
     $busyTimes = array();
     foreach ($this->objects as $object) {
         foreach ($object->getBaseComponents() as $component) {
             switch ($component->name) {
                 case 'VEVENT':
                     $FBTYPE = 'BUSY';
                     if (isset($component->TRANSP) && strtoupper($component->TRANSP) === 'TRANSPARENT') {
                         break;
                     }
                     if (isset($component->STATUS)) {
                         $status = strtoupper($component->STATUS);
                         if ($status === 'CANCELLED') {
                             break;
                         }
                         if ($status === 'TENTATIVE') {
                             $FBTYPE = 'BUSY-TENTATIVE';
                         }
                     }
                     $times = array();
                     if ($component->RRULE) {
                         $iterator = new Sabre_VObject_RecurrenceIterator($object, (string) $component->uid);
                         if ($this->start) {
                             $iterator->fastForward($this->start);
                         }
                         $maxRecurrences = 200;
                         while ($iterator->valid() && --$maxRecurrences) {
                             $startTime = $iterator->getDTStart();
                             if ($this->end && $startTime > $this->end) {
                                 break;
                             }
                             $times[] = array($iterator->getDTStart(), $iterator->getDTEnd());
                             $iterator->next();
                         }
                     } else {
                         $startTime = $component->DTSTART->getDateTime();
                         if ($this->end && $startTime > $this->end) {
                             break;
                         }
                         $endTime = null;
                         if (isset($component->DTEND)) {
                             $endTime = $component->DTEND->getDateTime();
                         } elseif (isset($component->DURATION)) {
                             $duration = Sabre_VObject_DateTimeParser::parseDuration((string) $component->DURATION);
                             $endTime = clone $startTime;
                             $endTime->add($duration);
                         } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
                             $endTime = clone $startTime;
                             $endTime->modify('+1 day');
                         } else {
                             // The event had no duration (0 seconds)
                             break;
                         }
                         $times[] = array($startTime, $endTime);
                     }
                     foreach ($times as $time) {
                         if ($this->end && $time[0] > $this->end) {
                             break;
                         }
                         if ($this->start && $time[1] < $this->start) {
                             break;
                         }
                         $busyTimes[] = array($time[0], $time[1], $FBTYPE);
                     }
                     break;
                 case 'VFREEBUSY':
                     foreach ($component->FREEBUSY as $freebusy) {
                         $fbType = isset($freebusy['FBTYPE']) ? strtoupper($freebusy['FBTYPE']) : 'BUSY';
                         // Skipping intervals marked as 'free'
                         if ($fbType === 'FREE') {
                             continue;
                         }
                         $values = explode(',', $freebusy);
                         foreach ($values as $value) {
                             list($startTime, $endTime) = explode('/', $value);
                             $startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime);
                             if (substr($endTime, 0, 1) === 'P' || substr($endTime, 0, 2) === '-P') {
                                 $duration = Sabre_VObject_DateTimeParser::parseDuration($endTime);
                                 $endTime = clone $startTime;
                                 $endTime->add($duration);
                             } else {
                                 $endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime);
                             }
                             if ($this->start && $this->start > $endTime) {
                                 continue;
                             }
                             if ($this->end && $this->end < $startTime) {
                                 continue;
                             }
                             $busyTimes[] = array($startTime, $endTime, $fbType);
                         }
                     }
                     break;
             }
         }
     }
     if ($this->baseObject) {
         $calendar = $this->baseObject;
     } else {
         $calendar = new Sabre_VObject_Component('VCALENDAR');
         $calendar->version = '2.0';
         $calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN';
         $calendar->calscale = 'GREGORIAN';
     }
     $vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
     $calendar->add($vfreebusy);
     if ($this->start) {
         $dtstart = new Sabre_VObject_Property_DateTime('DTSTART');
         $dtstart->setDateTime($this->start, Sabre_VObject_Property_DateTime::UTC);
         $vfreebusy->add($dtstart);
     }
     if ($this->end) {
         $dtend = new Sabre_VObject_Property_DateTime('DTEND');
         $dtend->setDateTime($this->start, Sabre_VObject_Property_DateTime::UTC);
         $vfreebusy->add($dtend);
     }
     $dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP');
     $dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC);
     $vfreebusy->add($dtstamp);
     foreach ($busyTimes as $busyTime) {
         $busyTime[0]->setTimeZone(new DateTimeZone('UTC'));
         $busyTime[1]->setTimeZone(new DateTimeZone('UTC'));
         $prop = new Sabre_VObject_Property('FREEBUSY', $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z'));
         $prop['FBTYPE'] = $busyTime[2];
         $vfreebusy->add($prop);
     }
     return $calendar;
 }
예제 #12
0
 /**
  * Returns a Sabre_Vobject_Component representing this object.
  *
  * @param subevents All events with the uid of this one. If not given, these will be fetched from the database.
  *
  * @return Sabre_VObject_Component representing $this.
  */
 public function asVObject($subevents = null)
 {
     $vobject = new Sabre_VObject_Component('vevent');
     if ($this->summary) {
         $vobject->add('summary', $this->summary);
     }
     if ($this->description) {
         $vobject->add('description', $this->description);
     }
     if ($this->comments) {
         $vobject->add('comment', $this->comments);
     }
     if ($this->location) {
         $vobject->add('location', $this->location);
     }
     if ($this->recurrenceId) {
         $recurrenceId = new Datetime($this->recurrenceId);
         $vobject->add('recurrence-id', $recurrenceId->format('Ymd\\THis\\Z'));
     } else {
         if ($this->rrule) {
             $vobject->add('rrule', $this->rrule);
             $exdates = array();
             foreach ($this->getExcludedDates() as $d) {
                 $exdates[] = $d->format('Ymd\\THis\\Z');
             }
             if (!empty($exdates)) {
                 // The problem here ist that if we change a single occurrence of an recurring event in P6, we mark the
                 // occurrence as excluded in the original event. In caldav, the exclusion takes precedence over the
                 // extracted event, which means that events that have been changed will not show up in caldav clients.
                 // To go around this, we filter these dates out of the excluded dates.
                 if (is_null($subevents)) {
                     $subevents = $this->fetchByUid($this->uid);
                 }
                 $subeventDates = array();
                 foreach ($subevents as $e) {
                     if ($e->recurrenceId) {
                         $dt = new Datetime($e->recurrenceId);
                         $subeventDates[] = $dt->format('Ymd\\THis\\Z');
                     }
                 }
                 $exdates = array_diff($exdates, $subeventDates);
                 $vobject->add('exdate', implode(',', $exdates));
             }
         }
     }
     $start = new Datetime('@' . Phprojekt_Converter_Time::userToUtc($this->start));
     $vobject->add('dtstart', $start->format('Ymd\\THis\\Z'));
     $end = new Datetime('@' . Phprojekt_Converter_Time::userToUtc($this->end));
     $vobject->add('dtend', $end->format('Ymd\\THis\\Z'));
     $lastMod = new DateTime($this->lastModified);
     $vobject->add('dtstamp', $lastMod->format('Ymd\\THis\\Z'));
     $vobject->add('uid', $this->uid);
     return $vobject;
 }
예제 #13
0
 /**
  * As defined in Sabre_CalDAV_Backend_Abstract
  *
  * Retrieves a single Calendar object.
  *
  * @param string $calendarId The id of the calendar. Corresponds to the id of the user it belongs to.
  * @param string $objectUri  The uri of the calendarobject to retrieve.
  *
  * @return array As specified by SabreDAV.
  */
 public function getCalendarObject($calendarId, $objectUri)
 {
     $db = Phprojekt::getInstance()->getDb();
     $events = new Calendar2_Models_Calendar2();
     $events = $events->fetchAll($db->quoteInto('uri = ?', $objectUri));
     if (!is_array($events) || empty($events)) {
         return array();
     }
     $calendarData = new Sabre_VObject_Component('vcalendar');
     $calendarData->add('version', '2.0');
     $calendarData->add('prodid', 'Phprojekt ' . Phprojekt::getVersion());
     $lastModified = $events[0]->lastModified;
     foreach ($events as $e) {
         $calendarData->add($e->asVObject($events));
         $lastModified = max($lastModified, $e->lastModified);
     }
     $lastModified = new Datetime($lastModified);
     return array('id' => $events[0]->uid, 'uri' => $objectUri, 'lastmodified' => $lastModified->format('Ymd\\THis\\Z'), 'calendarid' => $calendarId, 'calendardata' => $calendarData->serialize());
 }
 public static function createVCalendarFromRequest($request)
 {
     $vcalendar = new Sabre_VObject_Component('VCALENDAR');
     $vcalendar->add('PRODID', 'ownCloud Calendar');
     $vcalendar->add('VERSION', '2.0');
     $now = new DateTime();
     $vevent = new Sabre_VObject_Component('VEVENT');
     $vcalendar->add($vevent);
     $created = new Sabre_VObject_Element_DateTime('CREATED');
     $created->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
     $vevent->add($created);
     $uid = self::createUID();
     $vevent->add('UID', $uid);
     return self::updateVCalendarFromRequest($request, $vcalendar);
 }
예제 #15
0
 /**
  * @expectedException Sabre_DAV_Exception
  */
 public function testInTimeRangeInvalidComponent()
 {
     $valarm = Sabre_VObject_Component::create('VALARM');
     $valarm->TRIGGER = '-P1D';
     $valarm->TRIGGER['RELATED'] = 'END';
     $vjournal = Sabre_VObject_Component::create('VJOURNAL');
     $vjournal->add($valarm);
     $valarm->isInTimeRange(new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'));
 }
require_once '../../../lib/base.php';
$aid = $_POST['id'];
$l10n = new OC_L10N('contacts');
// Check if we are a user
OC_JSON::checkLoggedIn();
OC_JSON::checkAppEnabled('contacts');
$addressbook = OC_Contacts_Addressbook::find($aid);
if ($addressbook === false || $addressbook['userid'] != OC_USER::getUser()) {
    OC_JSON::error(array('data' => array('message' => $l10n->t('This is not your addressbook.'))));
    // Same here (as with the contact error). Could this error be improved?
    exit;
}
$fn = $_POST['fn'];
$values = $_POST['value'];
$parameters = $_POST['parameters'];
$vcard = new Sabre_VObject_Component('VCARD');
$vcard->add(new Sabre_VObject_Property('FN', $fn));
$vcard->add(new Sabre_VObject_Property('UID', OC_Contacts_VCard::createUID()));
foreach (array('ADR', 'TEL', 'EMAIL', 'ORG') as $propname) {
    $value = $values[$propname];
    if (isset($parameters[$propname])) {
        $prop_parameters = $parameters[$propname];
    } else {
        $prop_parameters = array();
    }
    OC_Contacts_VCard::addVCardProperty($vcard, $propname, $value, $prop_parameters);
}
$id = OC_Contacts_VCard::add($aid, $vcard->serialize());
$details = OC_Contacts_VCard::structureContact($vcard);
$name = $details['FN'][0]['value'];
$tmpl = new OC_Template('contacts', 'part.details');
예제 #17
0
 public function __isset($name)
 {
     return $this->vobject->__isset($name);
 }
예제 #18
0
 function testGetDateTimeBadTimeZone()
 {
     $default = date_default_timezone_get();
     date_default_timezone_set('Canada/Eastern');
     $elem = new Sabre_VObject_Element_DateTime('DTSTART', '19850704T013000');
     $elem['TZID'] = 'Moon';
     $event = new Sabre_VObject_Component('VEVENT');
     $event->add($elem);
     $timezone = new Sabre_VObject_Component('VTIMEZONE');
     $timezone->TZID = 'Moon';
     $timezone->{'X-LIC-LOCATION'} = 'Moon';
     $calendar = new Sabre_VObject_Component('VCALENDAR');
     $calendar->add($event);
     $calendar->add($timezone);
     $dt = $elem->getDateTime();
     $this->assertInstanceOf('DateTime', $dt);
     $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
     $this->assertEquals('Canada/Eastern', $dt->getTimeZone()->getName());
     $this->assertEquals(Sabre_VObject_Element_DateTime::LOCALTZ, $elem->getDateType());
     date_default_timezone_set($default);
 }
예제 #19
0
 function testSerializeChildren()
 {
     $comp = new Sabre_VObject_Component('VCALENDAR');
     $comp->children = array(new Sabre_VObject_Component('VEVENT'), new Sabre_VObject_Component('VTODO'));
     $this->assertEquals("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n", $comp->serialize());
 }
예제 #20
0
 /**
  * Returns free-busy information for a specific address. The returned 
  * data is an array containing the following properties:
  *
  * calendar-data : A VFREEBUSY VObject
  * request-status : an iTip status code.
  * href: The principal's email address, as requested
  *
  * The following request status codes may be returned:
  *   * 2.0;description
  *   * 3.7;description
  *
  * @param string $email address
  * @param DateTime $start
  * @param DateTime $end
  * @param Sabre_VObject_Component $request 
  * @return Sabre_VObject_Component 
  */
 protected function getFreeBusyForEmailTine20($email, DateTime $start, DateTime $end, Sabre_VObject_Component $request)
 {
     if (substr($email, 0, 7) === 'mailto:') {
         $email = substr($email, 7);
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' serach freebusy of ' . $email);
     }
     // resolve email address to contact
     $filter = new Addressbook_Model_ContactFilter(array(array('field' => 'containerType', 'operator' => 'equals', 'value' => 'all'), array('field' => 'type', 'operator' => 'equals', 'value' => Addressbook_Model_Contact::CONTACTTYPE_USER), array('field' => 'email', 'operator' => 'equals', 'value' => $email)));
     $contact = Addressbook_Controller_Contact::getInstance()->search($filter)->getFirstRecord();
     if ($contact === null) {
         return array('request-status' => '3.7;Could not find principal', 'href' => 'mailto:' . $email);
     }
     $period = array(array('from' => new Tinebase_DateTime($start->format(Tinebase_Record_Abstract::ISO8601LONG), 'UTC'), 'until' => new Tinebase_DateTime($end->format(Tinebase_Record_Abstract::ISO8601LONG), 'UTC')));
     $attendees = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(new Calendar_Model_Attender(array('user_id' => $contact->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER))));
     $freeBusyInfo = Calendar_Controller_Event::getInstance()->getFreeBusyInfo($period, $attendees);
     $vcalendar = new Sabre_VObject_Component('VCALENDAR');
     $vcalendar->VERSION = '2.0';
     $vcalendar->METHOD = 'REPLY';
     $vcalendar->CALSCALE = 'GREGORIAN';
     $vcalendar->PRODID = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
     $vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
     $vcalendar->add($vfreebusy);
     $vfreebusy->DTSTAMP = $request->VFREEBUSY->dtstart->value;
     $vfreebusy->DTSTART = $request->VFREEBUSY->dtstart->value;
     $vfreebusy->DTEND = $request->VFREEBUSY->dtend->value;
     #$attendee = new Sabre_VObject_Property('ATTENDEE', 'mailto:' . $contact->email);
     #$attendee->add('CN', $contact->n_fileas);
     #$vfreebusy->add($attendee);
     foreach ($freeBusyInfo as $busyInfo) {
         $busy = $busyInfo->dtstart->format('Ymd\\THis\\Z') . '/' . $busyInfo->dtend->format('Ymd\\THis\\Z');
         $freebusy = new Sabre_VObject_Property('FREEBUSY', $busy);
         $freebusy->add('FBTYPE', 'BUSY');
         $vfreebusy->add($freebusy);
     }
     $vcalendar->VFREEBUSY->ATTENDEE = 'mailto:' . $email;
     $vcalendar->VFREEBUSY->UID = (string) $request->VFREEBUSY->UID;
     return array('calendar-data' => $vcalendar, 'request-status' => '2.0;Success', 'href' => 'mailto:' . $email);
 }
예제 #21
0
 protected function _getCalendarVTimezone()
 {
     $timezone = Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::TIMEZONE, Tinebase_Core::getUser()->getId());
     // create vcalendar object with timezone information
     $vcalendar = new Sabre_VObject_Component('CALENDAR');
     $vcalendar->add(new Sabre_VObject_Component_VTimezone($timezone));
     // Taking out \r to not screw up the xml output
     return str_replace("\r", "", $vcalendar->serialize());
 }
예제 #22
0
 /**
  * Converts a timecard join project join module row to a vobject string.
  *
  * @param array $entry
  *
  * @return string
  */
 private function _getDataForEntry(array $entry)
 {
     $v = new Sabre_VObject_Component('vevent');
     if (1 == $entry['project_id']) {
         $v->add('summary', Phprojekt::getInstance()->translate('Unassigned'));
     } else {
         $v->add('summary', $entry['title'] . ' [' . $entry['project_id'] . ']');
     }
     $notes = trim($entry['notes']);
     if (!is_null($entry['module_id'])) {
         if ($notes) {
             $notes .= "\n";
         }
         $notes .= Phprojekt::getInstance()->translate('There is an attachment of type ') . Phprojekt::getInstance()->translate($entry['label']);
     }
     if ($notes) {
         $v->add('description', $notes);
     }
     $start = new DateTime('@' . Phprojekt_Converter_Time::userToUtc($entry['start_datetime']));
     $end = substr($entry['start_datetime'], 0, 11) . $entry['end_time'];
     $end = new DateTime('@' . Phprojekt_Converter_Time::userToUtc($end));
     $v->add('dtstart', $start->format('Ymd\\THis\\Z'));
     $v->add('dtend', $end->format('Ymd\\THis\\Z'));
     $v->add('uid', 'phprojekt-timecard-entry' . $entry['uid']);
     $calendarData = new Sabre_VObject_Component('vcalendar');
     $calendarData->add('version', '2.0');
     $calendarData->add('prodid', 'Phprojekt ' . Phprojekt::getVersion());
     $calendarData->add($v);
     return $calendarData->serialize();
 }
예제 #23
0
 function testSerializeOrder()
 {
     $comp = new Sabre_VObject_Component('VCALENDAR');
     $comp->add(new Sabre_VObject_Component('VEVENT'));
     $comp->add('PROP1', 'BLABLA');
     $comp->add('VERSION', '2.0');
     $comp->add(new Sabre_VObject_Component('VTIMEZONE'));
     $str = $comp->serialize();
     $this->assertEquals("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPROP1:BLABLA\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", $str);
 }
예제 #24
0
 /**
  * parse VEVENT part of VCALENDAR
  * 
  * @param  Sabre_VObject_Component  $_vevent  the VEVENT to parse
  * @param  Calendar_Model_Event     $_event   the Tine 2.0 event to update
  */
 protected function _convertVevent(Sabre_VObject_Component $_vevent, Calendar_Model_Event $_event)
 {
     $event = $_event;
     $newAttendees = array();
     // unset supported fields
     foreach ($this->_supportedFields as $field) {
         if ($field == 'alarms') {
             $event->{$field} = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm');
         } else {
             $event->{$field} = null;
         }
     }
     foreach ($_vevent->children() as $property) {
         switch ($property->name) {
             case 'CREATED':
             case 'DTSTAMP':
                 // do nothing
                 break;
             case 'LAST-MODIFIED':
                 $event->last_modified_time = new Tinebase_DateTime($property->value);
                 break;
             case 'ATTENDEE':
                 $newAttendees[] = $this->_getAttendee($property);
                 break;
             case 'CLASS':
                 if (in_array($property->value, array(Calendar_Model_Event::CLASS_PRIVATE, Calendar_Model_Event::CLASS_PUBLIC))) {
                     $event->class = $property->value;
                 } else {
                     $event->class = Calendar_Model_Event::CLASS_PUBLIC;
                 }
                 break;
             case 'DTEND':
                 if (isset($property['VALUE']) && strtoupper($property['VALUE']) == 'DATE') {
                     // all day event
                     $event->is_all_day_event = true;
                     $dtend = $this->_convertToTinebaseDateTime($property, TRUE);
                     // whole day events ends at 23:59:59 in Tine 2.0 but 00:00 the next day in vcalendar
                     $dtend->subSecond(1);
                 } else {
                     $event->is_all_day_event = false;
                     $dtend = $this->_convertToTinebaseDateTime($property);
                 }
                 $event->dtend = $dtend;
                 break;
             case 'DTSTART':
                 if (isset($property['VALUE']) && strtoupper($property['VALUE']) == 'DATE') {
                     // all day event
                     $event->is_all_day_event = true;
                     $dtstart = $this->_convertToTinebaseDateTime($property, TRUE);
                 } else {
                     $event->is_all_day_event = false;
                     $dtstart = $this->_convertToTinebaseDateTime($property);
                 }
                 $event->originator_tz = $dtstart->getTimezone()->getName();
                 $event->dtstart = $dtstart;
                 break;
             case 'SEQUENCE':
                 $event->seq = $property->value;
                 break;
             case 'DESCRIPTION':
             case 'LOCATION':
             case 'UID':
             case 'SUMMARY':
                 $key = strtolower($property->name);
                 $event->{$key} = $property->value;
                 break;
             case 'ORGANIZER':
                 if (preg_match('/mailto:(?P<email>.*)/i', $property->value, $matches)) {
                     // it's not possible to change the organizer by spec
                     if (empty($event->organizer)) {
                         $name = isset($property['CN']) ? $property['CN']->value : $matches['email'];
                         $contact = Calendar_Model_Attender::resolveEmailToContact(array('email' => $matches['email'], 'lastName' => $name));
                         $event->organizer = $contact->getId();
                     }
                     // Lightning attaches organizer ATTENDEE properties to ORGANIZER property and does not add an ATTENDEE for the organizer
                     if (isset($property['PARTSTAT'])) {
                         $newAttendees[] = $this->_getAttendee($property);
                     }
                 }
                 break;
             case 'RECURRENCE-ID':
                 // original start of the event
                 $event->recurid = $this->_convertToTinebaseDateTime($property);
                 // convert recurrence id to utc
                 $event->recurid->setTimezone('UTC');
                 break;
             case 'RRULE':
                 $event->rrule = $property->value;
                 // convert date format
                 $event->rrule = preg_replace_callback('/UNTIL=([\\dTZ]+)(?=;?)/', function ($matches) {
                     if (strlen($matches[1]) < 10) {
                         $dtUntil = date_create($matches[1], new DateTimeZone((string) Tinebase_Core::get(Tinebase_Core::USERTIMEZONE)));
                         $dtUntil->setTimezone(new DateTimeZone('UTC'));
                     } else {
                         $dtUntil = date_create($matches[1]);
                     }
                     return 'UNTIL=' . $dtUntil->format(Tinebase_Record_Abstract::ISO8601LONG);
                 }, $event->rrule);
                 // remove additional days from BYMONTHDAY property
                 $event->rrule = preg_replace('/(BYMONTHDAY=)([\\d]+)([,\\d]+)/', '$1$2', $event->rrule);
                 // process exceptions
                 if (isset($_vevent->EXDATE)) {
                     $exdates = new Tinebase_Record_RecordSet('Calendar_Model_Event');
                     foreach ($_vevent->EXDATE as $exdate) {
                         foreach ($exdate->getDateTimes() as $exception) {
                             if (isset($exdate['VALUE']) && strtoupper($exdate['VALUE']) == 'DATE') {
                                 $recurid = new Tinebase_DateTime($exception->format(Tinebase_Record_Abstract::ISO8601LONG), (string) Tinebase_Core::get(Tinebase_Core::USERTIMEZONE));
                             } else {
                                 $recurid = new Tinebase_DateTime($exception->format(Tinebase_Record_Abstract::ISO8601LONG), $exception->getTimezone());
                             }
                             $recurid->setTimezone(new DateTimeZone('UTC'));
                             $eventException = new Calendar_Model_Event(array('recurid' => $recurid, 'is_deleted' => true));
                             $exdates->addRecord($eventException);
                         }
                     }
                     $event->exdate = $exdates;
                 }
                 break;
             case 'TRANSP':
                 if (in_array($property->value, array(Calendar_Model_Event::TRANSP_OPAQUE, Calendar_Model_Event::TRANSP_TRANSP))) {
                     $event->transp = $property->value;
                 } else {
                     $event->transp = Calendar_Model_Event::TRANSP_TRANSP;
                 }
                 break;
             case 'UID':
                 // it's not possible to change the uid by spec
                 if (!empty($event->uid)) {
                     continue;
                 }
                 $event->uid = $property->value;
                 break;
             case 'VALARM':
                 foreach ($property as $valarm) {
                     switch (strtoupper($valarm->TRIGGER['VALUE']->value)) {
                         # TRIGGER;VALUE=DATE-TIME:20111031T130000Z
                         case 'DATE-TIME':
                             //@TODO fixme
                             $alarmTime = new Tinebase_DateTime($valarm->TRIGGER->value);
                             $alarmTime->setTimezone('UTC');
                             $alarm = new Tinebase_Model_Alarm(array('alarm_time' => $alarmTime, 'minutes_before' => 'custom', 'model' => 'Calendar_Model_Event'));
                             $event->alarms->addRecord($alarm);
                             break;
                             # TRIGGER;VALUE=DURATION:-PT1H15M
                         # TRIGGER;VALUE=DURATION:-PT1H15M
                         case 'DURATION':
                         default:
                             $alarmTime = $this->_convertToTinebaseDateTime($_vevent->DTSTART);
                             $alarmTime->setTimezone('UTC');
                             preg_match('/(?P<invert>[+-]?)(?P<spec>P.*)/', $valarm->TRIGGER->value, $matches);
                             $duration = new DateInterval($matches['spec']);
                             $duration->invert = !!($matches['invert'] === '-');
                             $alarm = new Tinebase_Model_Alarm(array('alarm_time' => $alarmTime->add($duration), 'minutes_before' => $duration->format('%d') * 60 * 24 + $duration->format('%h') * 60 + $duration->format('%i'), 'model' => 'Calendar_Model_Event'));
                             $event->alarms->addRecord($alarm);
                             break;
                     }
                 }
                 break;
             case 'CATEGORIES':
                 // @todo handle categories
                 break;
             case 'X-MOZ-LASTACK':
                 $lastAck = $this->_convertToTinebaseDateTime($property);
                 break;
             case 'X-MOZ-SNOOZE-TIME':
                 $snoozeTime = $this->_convertToTinebaseDateTime($property);
                 break;
             default:
                 break;
         }
     }
     // merge old and new attendees
     Calendar_Model_Attender::emailsToAttendee($event, $newAttendees);
     if (($ownAttendee = Calendar_Model_Attender::getOwnAttender($event->attendee)) !== null) {
         if (isset($lastAck)) {
             $ownAttendee->alarm_ack_time = $lastAck;
         }
         if (isset($snoozeTime)) {
             $ownAttendee->alarm_snooze_time = $snoozeTime;
         }
     }
     if (empty($event->seq)) {
         $event->seq = 0;
     }
     if (empty($event->class)) {
         $event->class = Calendar_Model_Event::CLASS_PUBLIC;
     }
     // convert all datetime fields to UTC
     $event->setTimezone('UTC');
 }
예제 #25
0
 /**
  * converts Addressbook_Model_Contact to vcard
  * 
  * @param  Addressbook_Model_Contact  $_record
  * @return string
  */
 public function fromTine20Model(Tinebase_Record_Abstract $_record)
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' contact ' . print_r($_record->toArray(), true));
     }
     $card = new Sabre_VObject_Component('VCARD');
     // required vcard fields
     $card->add(new Sabre_VObject_Property('VERSION', '3.0'));
     $card->add(new Sabre_VObject_Property('FN', $_record->n_fileas));
     $card->add(new Sabre_VObject_Element_MultiValue('N', array($_record->n_family, $_record->n_given)));
     $card->add(new Sabre_VObject_Property('PRODID', '-//tine20.org//Tine 2.0//EN'));
     $card->add(new Sabre_VObject_Property('UID', $_record->getId()));
     // optional fields
     $card->add(new Sabre_VObject_Element_MultiValue('ORG', array($_record->org_name, $_record->org_unit)));
     $card->add(new Sabre_VObject_Property('TITLE', $_record->title));
     $tel = new Sabre_VObject_Property('TEL', $_record->tel_work);
     $tel->add('TYPE', 'WORK');
     $card->add($tel);
     $tel = new Sabre_VObject_Property('TEL', $_record->tel_home);
     $tel->add('TYPE', 'HOME');
     $card->add($tel);
     $tel = new Sabre_VObject_Property('TEL', $_record->tel_cell);
     $tel->add('TYPE', 'CELL');
     $card->add($tel);
     $tel = new Sabre_VObject_Property('TEL', $_record->tel_pager);
     $tel->add('TYPE', 'PAGER');
     $card->add($tel);
     $tel = new Sabre_VObject_Property('TEL', $_record->tel_fax);
     $tel->add('TYPE', 'FAX');
     $card->add($tel);
     #$tel = new Sabre_VObject_Property('TEL', $_record->tel_fax_home);
     #$tel->add('TYPE', 'FAX');
     #$tel->add('TYPE', 'HOME');
     #$card->add($tel);
     $adr = new Sabre_VObject_Element_MultiValue('ADR', array(null, $_record->adr_one_street2, $_record->adr_one_street, $_record->adr_one_locality, $_record->adr_one_region, $_record->adr_one_postalcode, $_record->adr_one_countryname));
     $adr->add('TYPE', 'WORK');
     $card->add($adr);
     $adr = new Sabre_VObject_Element_MultiValue('ADR', array(null, $_record->adr_two_street2, $_record->adr_two_street, $_record->adr_two_locality, $_record->adr_two_region, $_record->adr_two_postalcode, $_record->adr_two_countryname));
     $adr->add('TYPE', 'HOME');
     $card->add($adr);
     $card->add(new Sabre_VObject_Property('EMAIL;TYPE=work', $_record->email));
     $card->add(new Sabre_VObject_Property('EMAIL;TYPE=home', $_record->email_home));
     $card->add(new Sabre_VObject_Property('URL;TYPE=work', $_record->url));
     $card->add(new Sabre_VObject_Property('URL;TYPE=home', $_record->url_home));
     $card->add(new Sabre_VObject_Property('NOTE', $_record->note));
     if (!empty($_record->jpegphoto)) {
         try {
             $image = Tinebase_Controller::getInstance()->getImage('Addressbook', $_record->getId());
             $jpegData = $image->getBlob('image/jpeg');
             $photo = new Sabre_VObject_Property('PHOTO', $jpegData);
             $photo->add('ENCODING', 'b');
             $photo->add('TYPE', 'JPEG');
             $card->add($photo);
         } catch (Exception $e) {
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Image for contact {$_record->getId()} not found or invalid");
         }
     }
     if (isset($_record->tags) && count($_record->tags) > 0) {
         $card->add(new Sabre_VObject_Property('CATEGORIES', Sabre_VObject_Element_List((array) $_record->tags->name)));
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' card ' . $card->serialize());
     }
     return $card;
 }
 /**
  * @depends testValues
  */
 function testOverridenEventNoValuesExpected()
 {
     $vcal = Sabre_VObject_Component::create('VCALENDAR');
     $ev1 = Sabre_VObject_Component::create('VEVENT');
     $ev1->UID = 'overridden';
     $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3';
     $ev1->DTSTART = '20120124T120000Z';
     $ev1->SUMMARY = 'baseEvent';
     $vcal->add($ev1);
     // ev2 overrides an event, and puts it 6 days earlier instead.
     $ev2 = Sabre_VObject_Component::create('VEVENT');
     $ev2->UID = 'overridden';
     $ev2->{'RECURRENCE-ID'} = '20120131T120000Z';
     $ev2->DTSTART = '20120125T120000Z';
     $ev2->SUMMARY = 'Override!';
     $vcal->add($ev2);
     $it = new Sabre_VObject_RecurrenceIterator($vcal, 'overridden');
     $dates = array();
     $summaries = array();
     // The reported problem was specifically related to the VCALENDAR
     // expansion. In this parcitular case, we had to forward to the 28th of
     // january.
     $it->fastForward(new DateTime('2012-01-28 23:00:00'));
     // We stop the loop when it hits the 6th of februari. Normally this
     // iterator would hit 24, 25 (overriden from 31) and 7 feb but because
     // we 'filter' from the 28th till the 6th, we should get 0 results.
     while ($it->valid() && $it->getDTSTart() < new DateTime('2012-02-06 23:00:00')) {
         $dates[] = $it->getDTStart();
         $summaries[] = (string) $it->getEventObject()->SUMMARY;
         $it->next();
     }
     $this->assertEquals(array(), $dates);
     $this->assertEquals(array(), $summaries);
 }