/** * Parses an entire document. * * @return void */ protected function parseDocument() { $line = $this->readLine(); // BOM is ZERO WIDTH NO-BREAK SPACE (U+FEFF). // It's 0xEF 0xBB 0xBF in UTF-8 hex. if (3 <= strlen($line) && ord($line[0]) === 0xef && ord($line[1]) === 0xbb && ord($line[2]) === 0xbf) { $line = substr($line, 3); } switch (strtoupper($line)) { case 'BEGIN:VCALENDAR': $class = isset(VCalendar::$componentMap['VCALENDAR']) ? VCalendar::$componentMap[$name] : 'Sabre\\VObject\\Component\\VCalendar'; break; case 'BEGIN:VCARD': $class = isset(VCard::$componentMap['VCARD']) ? VCard::$componentMap['VCARD'] : 'Sabre\\VObject\\Component\\VCard'; break; default: throw new ParseException('This parser only supports VCARD and VCALENDAR files'); } $this->root = new $class([], false); while (true) { // Reading until we hit END: $line = $this->readLine(); if (strtoupper(substr($line, 0, 4)) === 'END:') { break; } $result = $this->parseLine($line); if ($result) { $this->root->add($result); } } $name = strtoupper(substr($line, 4)); if ($name !== $this->root->name) { throw new ParseException('Invalid MimeDir file. expected: "END:' . $this->root->name . '" got: "END:' . $name . '"'); } }
/** * Parses an entire document. * * @return void */ protected function parseDocument() { $line = $this->readLine(); switch (strtoupper($line)) { case 'BEGIN:VCALENDAR': $class = isset(VCalendar::$componentMap['VCALENDAR']) ? VCalendar::$componentMap[$name] : 'Sabre\\VObject\\Component\\VCalendar'; break; case 'BEGIN:VCARD': $class = isset(VCard::$componentMap['VCARD']) ? VCard::$componentMap['VCARD'] : 'Sabre\\VObject\\Component\\VCard'; break; default: throw new ParseException('This parser only supports VCARD and VCALENDAR files'); } $this->root = new $class(array(), false); while (true) { // Reading until we hit END: $line = $this->readLine(); if (strtoupper(substr($line, 0, 4)) === 'END:') { break; } $result = $this->parseLine($line); if ($result) { $this->root->add($result); } } $name = strtoupper(substr($line, 4)); if ($name !== $this->root->name) { throw new ParseException('Invalid MimeDir file. expected: "END:' . $this->root->name . '" got: "END:' . $name . '"'); } }
/** * Parses an entire document. * * @return void */ protected function parseDocument() { $line = $this->readLine(); switch (strtoupper($line)) { case 'BEGIN:VCALENDAR': $this->root = new VCalendar(array(), false); break; case 'BEGIN:VCARD': $this->root = new VCard(array(), false); break; default: throw new ParseException('This parser only support VCARD and VCALENDAR files'); } while (true) { // Reading until we hit END: $line = $this->readLine(); if (strtoupper(substr($line, 0, 4)) === 'END:') { break; } $result = $this->parseLine($line); if ($result) { $this->root->add($result); } } $name = strtoupper(substr($line, 4)); if ($name !== $this->root->name) { throw new ParseException('Invalid MimeDir file. expected: "END:' . $this->root->name . '" got: "END:' . $name . '"'); } }
/** * Create a property. * * @param Component $parentComponent * @param string $name * @param array $parameters * @param string $type * @param mixed $value * * @return void */ protected function createProperty(Component $parentComponent, $name, $parameters, $type, $value) { $property = $this->root->createProperty($name, null, $parameters, $type); $parentComponent->add($property); $property->setXmlValue($value); }
/** * Merges all calendar objects, and builds one big ics export * * @param array $nodes * @return string */ public function generateICS(array $nodes) { $calendar = new 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 = 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(); }
/** * add photo data to VCard * * @param Addressbook_Model_Contact $record * @param \Sabre\VObject\Component $card */ protected function _fromTine20ModelAddPhoto(Addressbook_Model_Contact $record, \Sabre\VObject\Component $card) { if (!empty($record->jpegphoto)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__); try { $jpegData = $record->getSmallContactImage($this->_maxPhotoSize); $card->add('PHOTO', $jpegData, array('TYPE' => 'JPEG', 'ENCODING' => 'b')); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Image for contact {$record->getId()} not found or invalid: {$e->getMessage()}"); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $e->getTraceAsString()); } } } }
/** * Returns a VTIMEZONE component for a Olson timezone identifier * with daylight transitions covering the given date range. * * @param string Timezone ID as used in PHP's Date functions * @param integer Unix timestamp with first date/time in this timezone * @param integer Unix timestap with last date/time in this timezone * * @return mixed A Sabre\VObject\Component object representing a VTIMEZONE definition * or false if no timezone information is available */ public static function get_vtimezone($tzid, $from = 0, $to = 0) { if (!$from) { $from = time(); } if (!$to) { $to = $from; } if (is_string($tzid)) { try { $tz = new \DateTimeZone($tzid); } catch (\Exception $e) { return false; } } else { if (is_a($tzid, '\\DateTimeZone')) { $tz = $tzid; } } if (!is_a($tz, '\\DateTimeZone')) { return false; } $year = 86400 * 360; $transitions = $tz->getTransitions($from - $year, $to + $year); $vt = new VObject\Component('VTIMEZONE'); $vt->TZID = $tz->getName(); $std = null; $dst = null; foreach ($transitions as $i => $trans) { $cmp = null; if ($i == 0) { $tzfrom = $trans['offset'] / 3600; continue; } if ($trans['isdst']) { $t_dst = $trans['ts']; $dst = new VObject\Component('DAYLIGHT'); $cmp = $dst; } else { $t_std = $trans['ts']; $std = new VObject\Component('STANDARD'); $cmp = $std; } if ($cmp) { $dt = new DateTime($trans['time']); $offset = $trans['offset'] / 3600; $cmp->DTSTART = $dt->format('Ymd\\THis'); $cmp->TZOFFSETFROM = sprintf('%s%02d%02d', $tzfrom >= 0 ? '+' : '', floor($tzfrom), ($tzfrom - floor($tzfrom)) * 60); $cmp->TZOFFSETTO = sprintf('%s%02d%02d', $offset >= 0 ? '+' : '', floor($offset), ($offset - floor($offset)) * 60); if (!empty($trans['abbr'])) { $cmp->TZNAME = $trans['abbr']; } $tzfrom = $offset; $vt->add($cmp); } // we covered the entire date range if ($std && $dst && min($t_std, $t_dst) < $from && max($t_std, $t_dst) > $to) { break; } } // add X-MICROSOFT-CDO-TZID if available $microsoftExchangeMap = array_flip(VObject\TimeZoneUtil::$microsoftExchangeMap); if (array_key_exists($tz->getName(), $microsoftExchangeMap)) { $vt->add('X-MICROSOFT-CDO-TZID', $microsoftExchangeMap[$tz->getName()]); } return $vt; }
/** * @depends testValues */ function testComplexExclusions() { $ev = new Component('VEVENT'); $ev->UID = 'bla'; $ev->RRULE = 'FREQ=YEARLY;COUNT=10'; $dtStart = new Property\DateTime('DTSTART'); $tz = new DateTimeZone('Canada/Eastern'); $dtStart->setDateTime(new DateTime('2011-01-01 13:50:20', $tz), Property\DateTime::LOCALTZ); $exDate1 = new Property\MultiDateTime('EXDATE'); $exDate1->setDateTimes(array(new DateTime('2012-01-01 13:50:20', $tz), new DateTime('2014-01-01 13:50:20', $tz)), Property\DateTime::LOCALTZ); $exDate2 = new Property\MultiDateTime('EXDATE'); $exDate2->setDateTimes(array(new DateTime('2016-01-01 13:50:20', $tz)), Property\DateTime::LOCALTZ); $ev->add($dtStart); $ev->add($exDate1); $ev->add($exDate2); $vcal = Component::create('VCALENDAR'); $vcal->add($ev); $it = new RecurrenceIterator($vcal, (string) $ev->uid); $this->assertEquals('yearly', $it->frequency); $this->assertEquals(1, $it->interval); $this->assertEquals(10, $it->count); $max = 20; $result = array(); foreach ($it as $k => $item) { $result[] = $item; $max--; if (!$max) { break; } } $this->assertEquals(array(new DateTime('2011-01-01 13:50:20', $tz), new DateTime('2013-01-01 13:50:20', $tz), new DateTime('2015-01-01 13:50:20', $tz), new DateTime('2017-01-01 13:50:20', $tz), new DateTime('2018-01-01 13:50:20', $tz), new DateTime('2019-01-01 13:50:20', $tz), new DateTime('2020-01-01 13:50:20', $tz)), $result); }
/** * @param CContact $oContact * @param \Sabre\VObject\Component $oVCard * @return void */ public static function UpdateVCardUrlsFromContact($oContact, &$oVCard) { $bFindHome = false; $bFindWork = false; if (empty($oContact->HomeWeb)) { $bFindHome = true; } if (empty($oContact->BusinessWeb)) { $bFindWork = true; } if (isset($oVCard->URL)) { foreach ($oVCard->URL as $oUrl) { if ($oTypes = $oUrl['TYPE']) { if ($oTypes->has('HOME')) { if ($bFindHome) { unset($oUrl); } else { $oUrl->setValue($oContact->HomeWeb); $bFindHome = true; } } if ($oTypes->has('WORK')) { if ($bFindWork) { unset($oUrl); } else { $oUrl->setValue($oContact->BusinessWeb); $bFindWork = true; } } } } } if (!$bFindHome) { $oVCard->add('URL', $oContact->HomeWeb, array('TYPE' => array('HOME'))); } if (!$bFindWork) { $oVCard->add('URL', $oContact->BusinessWeb, array('TYPE' => array('WORK'))); } }
function testGetDateTimeBadTimeZone() { $default = date_default_timezone_get(); date_default_timezone_set('Canada/Eastern'); $elem = new DateTime('DTSTART', '19850704T013000'); $elem['TZID'] = 'Moon'; $event = new Component('VEVENT'); $event->add($elem); $timezone = new Component('VTIMEZONE'); $timezone->TZID = 'Moon'; $timezone->{'X-LIC-LOCATION'} = 'Moon'; $calendar = new 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(DateTime::LOCALTZ, $elem->getDateType()); date_default_timezone_set($default); }