format() публичный Метод

To format in languages other than English, use strftime() instead.
public format ( string $format ) : string
$format string
Результат string Formatted time.
Пример #1
0
 public function processRequest(Horde_Controller_Request $request, Horde_Controller_Response $response)
 {
     $this->_mapper = $GLOBALS['injector']->getInstance('Horde_Routes_Mapper');
     $this->_matchDict = new Horde_Support_Array($this->_mapper->match($request->getPath()));
     $injector = $this->getInjector();
     switch ($this->_matchDict->action) {
         case 'category':
             $driver = $injector->getInstance('Dolcore_Factory_Driver')->create($injector);
             $categories = $driver->getCategoriesApi();
             $discussionApi = $driver->getDiscussionApi();
             $category = $categories->getCategory($this->_matchDict->category);
             /* Write a category's currently running Umfragen */
             $now = new Horde_Date(time());
             $template = $this->getInjector()->createInstance('Horde_Template');
             $template->set('updated', $now->format(DATE_ATOM));
             $template->set('category_caption', $category->getCaption());
             $template->set('category_id', $category->id);
             $discussions = array();
             foreach ($discussionApi->listDiscussions(array('category' => $category->id)) as $discussion) {
                 $discussions[$discussion->id]['title'] = $discussion->text;
                 $discussions[$discussion->id]['details'] = $discussion->hintergrund;
                 $discussions[$discussion->id]['modified'] = $discussion->erstelldatum;
                 $discussions[$discussion->id]['id'] = Dolcore::getUrlFor('discussion', array('discussion_id' => $discussion->id), true, true);
                 $discussions[$discussion->id]['url'] = Dolcore::getUrlFor('discussion', array('discussion_id' => $discussion->id), true, true);
             }
             $template->set('discussions', $discussions);
             $response->setBody($template->fetch(DOLCORE_TEMPLATES . '/feeds/atom.xml'));
             break;
         case 'categories':
             break;
     }
 }
Пример #2
0
 /**
  * Constructor.
  *
  * @param array $config  Configuration key-value pairs.
  */
 public function __construct($config = array())
 {
     global $prefs, $registry;
     parent::__construct($config);
     $blank = new Horde_Url();
     $this->addNewButton(_("_New Event"), $blank, array('id' => 'kronolithNewEvent'));
     $this->newExtra = $blank->link(array_merge(array('id' => 'kronolithQuickEvent'), Horde::getAccessKeyAndTitle(_("Quick _insert"), false, true)));
     $sidebar = $GLOBALS['injector']->createInstance('Horde_View');
     /* Minical. */
     $today = new Horde_Date($_SERVER['REQUEST_TIME']);
     $sidebar->today = $today->format('F Y');
     $sidebar->weekdays = array();
     for ($i = $prefs->getValue('week_start_monday'), $c = $i + 7; $i < $c; $i++) {
         $weekday = Horde_Nls::getLangInfo(constant('DAY_' . ($i % 7 + 1)));
         $sidebar->weekdays[$weekday] = Horde_String::substr($weekday, 0, 2);
     }
     /* Calendars. */
     $sidebar->newShares = $registry->getAuth() && !$prefs->isLocked('default_share');
     $sidebar->admin = $registry->isAdmin();
     $sidebar->resourceAdmin = $registry->isAdmin() || $GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('resource_management');
     $sidebar->resources = $GLOBALS['conf']['resources']['enabled'];
     $sidebar->addRemote = !$prefs->isLocked('remote_cals');
     $remotes = unserialize($prefs->getValue('remote_cals'));
     $sidebar->showRemote = !($prefs->isLocked('remote_cals') && empty($remotes));
     $this->content = $sidebar->render('dynamic/sidebar');
 }
Пример #3
0
 /**
  *
  * @global Horde_Prefs $prefs
  * @param Horde_Date $date
  *
  * @return Kronolith_View_Month
  */
 public function __construct(Horde_Date $date)
 {
     global $prefs;
     $this->month = $date->month;
     $this->year = $date->year;
     // Need to calculate the start and length of the view.
     $this->date = new Horde_Date($date);
     $this->date->mday = 1;
     $this->_startday = $this->date->dayOfWeek();
     if (!$prefs->getValue('week_start_monday')) {
         $this->_startOfView = 1 - $this->_startday;
     } else {
         if ($this->_startday == Horde_Date::DATE_SUNDAY) {
             $this->_startOfView = -5;
         } else {
             $this->_startOfView = 2 - $this->_startday;
         }
     }
     $startDate = new Horde_Date($this->year, $this->month, $this->_startOfView);
     $this->_endDate = new Horde_Date($this->year, $this->month, Horde_Date_Utils::daysInMonth($this->month, $this->year) + 1);
     $this->_endDate->mday += (7 - ($this->_endDate->format('w') - $prefs->getValue('week_start_monday'))) % 7;
     if ($prefs->getValue('show_shared_side_by_side')) {
         $allCalendars = Kronolith::listInternalCalendars();
         $this->_currentCalendars = array();
         foreach ($GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS) as $id) {
             $this->_currentCalendars[$id] = $allCalendars[$id];
         }
     } else {
         $this->_currentCalendars = array('internal_0' => true);
     }
     try {
         $this->_events = Kronolith::listEvents($startDate, $this->_endDate);
     } catch (Exception $e) {
         $GLOBALS['notification']->push($e, 'horde.error');
         $this->_events = array();
     }
     if (!is_array($this->_events)) {
         $this->_events = array();
     }
 }
Пример #4
0
 /**
  * Output a human readable description of the recurrence rule.
  *
  * @return string
  * @since 2.1.0
  */
 public function toString($date_format)
 {
     $string = '';
     if ($this->hasRecurType(self::RECUR_DAILY)) {
         $string = _("Daily: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("day(s)");
     } elseif ($this->hasRecurType(self::RECUR_WEEKLY)) {
         $weekdays = array();
         if ($this->recurOnDay(Horde_Date::MASK_MONDAY)) {
             $weekdays[] = _("Monday");
         }
         if ($this->recurOnDay(Horde_Date::MASK_TUESDAY)) {
             $weekdays[] = _("Tuesday");
         }
         if ($this->recurOnDay(Horde_Date::MASK_WEDNESDAY)) {
             $weekdays[] = _("Wednesday");
         }
         if ($this->recurOnDay(Horde_Date::MASK_THURSDAY)) {
             $weekdays[] = _("Thursday");
         }
         if ($this->recurOnDay(Horde_Date::MASK_FRIDAY)) {
             $weekdays[] = _("Friday");
         }
         if ($this->recurOnDay(Horde_Date::MASK_SATURDAY)) {
             $weekdays[] = _("Saturday");
         }
         if ($this->recurOnDay(Horde_Date::MASK_SUNDAY)) {
             $weekdays[] = _("Sunday");
         }
         $string = _("Weekly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("week(s) on:") . ' ' . implode(', ', $weekdays);
     } elseif ($this->hasRecurType(self::RECUR_MONTHLY_DATE)) {
         $string = _("Monthly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("month(s)") . ' ' . _("on the same date");
     } elseif ($this->hasRecurType(self::RECUR_MONTHLY_WEEKDAY)) {
         $string = _("Monthly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("month(s)") . ' ' . _("on the same weekday");
     } elseif ($this->hasRecurType(self::RECUR_MONTHLY_LAST_WEEKDAY)) {
         $string = _("Monthly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("month(s)") . ' ' . _("on the same last weekday");
     } elseif ($this->hasRecurType(self::RECUR_YEARLY_DATE)) {
         $string = _("Yearly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("year(s) on the same date");
     } elseif ($this->hasRecurType(self::RECUR_YEARLY_DAY)) {
         $string = _("Yearly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("year(s) on the same day of the year");
     } elseif ($this->hasRecurType(self::RECUR_YEARLY_WEEKDAY)) {
         $string = _("Yearly: Recurs every") . ' ' . $this->getRecurInterval() . ' ' . _("year(s) on the same weekday and month of the year");
     }
     $string .= "\n" . _("Ends after") . ': ' . ($this->hasRecurEnd() ? $this->recurEnd->strftime($date_format) . ($this->recurEnd->hour == 23 && $this->recurEnd->min == 59 ? '' : ' ' . $this->recurEnd->format($date_format)) : ($this->getRecurCount() ? sprintf(_("%d times"), $this->getRecurCount()) : _("No end date")));
     if ($this->getExceptions()) {
         $string .= "\n" . _("Exceptions on") . ': ';
         foreach ($this->getExceptions() as $exception_date) {
             $string .= $this->_formatExceptionDate($exception_date, $date_format) . ' ';
         }
     }
     return $string;
 }
Пример #5
0
 /**
  * @dataProvider timezones
  */
 public function testFile($file)
 {
     $result = '';
     $ical = new Horde_Icalendar();
     $ical->parsevCalendar(file_get_contents($file));
     foreach ($ical->getComponents() as $component) {
         if ($component->getType() != 'vEvent') {
             continue;
         }
         $date = $component->getAttribute('DTSTART');
         if (is_array($date)) {
             continue;
         }
         $result .= str_replace("\r", '', $component->getAttribute('SUMMARY')) . "\n";
         $d = new Horde_Date($date);
         $result .= $d->format('H:i') . "\n";
     }
     $this->assertStringEqualsFile(__DIR__ . '/fixtures/vTimezone/' . basename($file, 'ics') . 'txt', $result, 'Failed parsing file ' . basename($file));
 }
Пример #6
0
 /**
  * Return the number of hours to offset a POOMCONTACTS:BIRTHDAY
  * or ANNIVERSARY field in an attempt to work around a bug in the
  * protocol - which doesn't define a standard time for birthdays to occur.
  *
  *  WP:
  *     Devices seem to send the birthdays at the entered date, with
  *     a time of 00:00:00 UTC during standard time and with 01:00:00 UTC
  *     during DST if the client's configured timezone observes it. No idea
  *     what purpose this serves since no timezone data is transmitted for
  *     birthday values.
  *
  *   iOS:
  *     Seems different based on version. iOS 5+, at least seems to send
  *     the birthday as midnight at the entered date in the device's timezone
  *     then converted to UTC. Some minor issues with offsets being off an
  *     hour or two for some timezones though.
  *
  *     iOS < 5 sends the birthday time part as the time the birthday
  *     was entered/edited on the device, converted to UTC, so it can't be
  *     trusted at all. The best we can do here is transform the date to
  *     midnight on date_default_timezone() converted to UTC.
  *
  *   Android:
  *     For contacts originating on the SERVER, the following is true:
  *
  *     Stock 4.3 Takes the down-synched bday value which is assumed to be
  *     UTC, does some magic to it (converts to milliseconds, creates a
  *     gregorian calendar object, then converts to YYYY-MM-DD). When
  *     sending the bday value up, it sends it up as-is. No conversion
  *     to/from UTC or local is done.
  *
  *     Stock 4.4.x does the above, but before sending the bday value,
  *     validates that it's in a correct format for sending to the server.
  *     This really only affects date data originally entered on the device
  *     for non-stock android clients.
  *
  *     There is some strange bit of code in Android that adds 1 to the
  *     DAY_OF_MONTH when HOUR_OF_DAY >= 12 in an attempt to "fix"
  *     birthday handling for GMT+n users. See:
  *     https://android.googlesource.com/platform/packages/apps/Exchange/+/32daacdd71b9de8fd5e3f59c37934e3e4a9fa972%5E!/exchange2/src/com/android/exchange/adapter/ContactsSyncAdapter.java
  *     Not sure what to make of it, or why it's not just converted to
  *     local tz when displaying but this probably breaks birthday handling
  *     for people in a few timezones.
  *
  *     For contacts originating on the CLIENT, the datetime is sent as
  *     08:00:00 UTC, and this seems to be regardless of the timezone set
  *     in the Android system.
  *
  *     Given all of this, it makes sense to me to ALWAYS send birthday
  *     data as occuring at 08:00:00 UTC for *native* Android clients.
  *
  *   BB 10+ expects it at 12:00:00 UTC
  *
  * @param Horde_Date $date  The date. This should normally be in the local
  *                          timezone if encoding the date for the client.
  *                          If decoding the date from the client, it will
  *                          normally be in UTC.
  * @param boolean $toEas    Convert from local to device if true.
  *                          DEFAULT: false
  *
  * @return Horde_Date  The date of the birthday/anniversary, with
  *                     any fixes applied for the current device. The
  *                     timezone set in the object will depend on the
  *                     client detected, and whether the date is being
  *                     encoding or decoding.
  */
 public function normalizePoomContactsDates($date, $toEas = false)
 {
     switch (Horde_String::lower($this->clientType)) {
         case self::TYPE_WP:
         case 'wp8':
             // Legacy. Remove in H6.
         // Legacy. Remove in H6.
         case 'wp':
             // Legacy. Remove in H6.
             if ($toEas) {
                 return new Horde_Date($date->format('Y-m-d'), 'UTC');
             } else {
                 $date = new Horde_Date($date->format('Y-m-d'));
                 return $date->setTimezone('UTC');
             }
         case self::TYPE_ANDROID:
             // Need to protect against clients that don't send the actual Android
             // version in the OS field.
             if (stripos($this->deviceType, 'samsung') === 0) {
                 // Samsung's native Contacts app works differently than stock
                 // Android, always sending as 00:00:00
                 if ($toEas) {
                     return new Horde_Date($date->format('Y-m-d'), 'UTC');
                 }
                 $date = new Horde_Date($date->format('Y-m-d'));
                 return $date->setTimezone('UTC');
             }
             if ($this->getMajorVersion() >= 4 && $this->getMajorVersion() <= 10) {
                 if ($toEas) {
                     return new Horde_Date($date->format('Y-m-d 08:00:00'), 'UTC');
                 } else {
                     $date = new Horde_Date($date->format('Y-m-d'));
                     return $date->setTimezone('UTC');
                 }
             } else {
                 // POOMCONTACTS:BIRTHDAY not really supported in early Android
                 // versions. Return as is.
                 return $date;
             }
         case self::TYPE_IPAD:
         case self::TYPE_IPHONE:
         case self::TYPE_IPOD:
             if ($this->getMajorVersion() >= 5) {
                 // iOS >= 5 handles it correctly more or less.
                 if ($toEas) {
                     return new Horde_Date($date->format('Y-m-d 00:00:00'));
                 } else {
                     return $date;
                 }
             } else {
                 if ($toEas) {
                     return new Horde_Date($date->format('Y-m-d'), 'UTC');
                 } else {
                     return new Horde_Date($date->format('Y-m-d'));
                 }
             }
         case self::TYPE_NINE:
             if ($toEas) {
                 return new Horde_Date($date->format('Y-m-d 00:00:00'));
             } else {
                 return $date;
             }
         case self::TYPE_BLACKBERRY:
             if ($toEas) {
                 return new Horde_Date($date->format('Y-m-d 12:00:00'), 'UTC');
             } else {
                 $date = new Horde_Date($date->format('Y-m-d'));
                 return $date->setTimezone('UTC');
             }
         case self::TYPE_TOUCHDOWN:
         case self::TYPE_UNKNOWN:
         default:
             return $date;
     }
 }
Пример #7
0
 /**
  * Calculate the offsets for the specified transition
  *
  * @param array $offsets      A TZ offset hash
  * @param array $transition   A transition hash
  * @param string $type        Transition type - dst or std
  *
  * @return array  A populated offset hash
  */
 protected static function _generateOffsetsForTransition(array $offsets, array $transition, $type)
 {
     // We can't use Horde_Date directly here, since it is unable to
     // properly convert to UTC from local ON the exact hour of a std -> dst
     // transition. This is due to a conversion to DateTime in the localtime
     // zone internally before the timezone change is applied
     $transitionDate = new DateTime($transition['time']);
     $transitionDate->setTimezone(new DateTimeZone('UTC'));
     $transitionDate = new Horde_Date($transitionDate);
     $offsets[$type . 'month'] = $transitionDate->format('n');
     $offsets[$type . 'day'] = $transitionDate->format('w');
     $offsets[$type . 'minute'] = (int) $transitionDate->format('i');
     $offsets[$type . 'hour'] = (int) $transitionDate->format('H');
     for ($i = 5; $i > 0; $i--) {
         if (self::_isNthOcurrenceOfWeekdayInMonth($transition['ts'], $i)) {
             $offsets[$type . 'week'] = $i;
             break;
         }
     }
     return $offsets;
 }
Пример #8
0
 private function _getEvents($dh, $startDate, $endDate)
 {
     $events = array();
     for ($date = new Horde_Date($startDate); $date->compareDate($endDate) <= 0; $date->mday++) {
         $holidays = $dh->getHolidayForDate($date->format('Y-m-d'), null, true);
         if (Date_Holidays::isError($holidays)) {
             Horde::log(sprintf('Unable to retrieve list of holidays from %s to %s', (string) $startDate, (string) $endDate), __FILE__, __LINE__);
             continue;
         }
         if (is_null($holidays)) {
             continue;
         }
         foreach ($holidays as $holiday) {
             $event = new Kronolith_Event_Holidays($this, $holiday);
             $events[] = $event;
         }
     }
     return $events;
 }
Пример #9
0
 /**
  * Returns a simple object suitable for json transport representing this
  * task.
  *
  * @param boolean $full        Whether to return all task details.
  * @param string $time_format  The date() format to use for time formatting.
  *
  * @return object  A simple object.
  */
 public function toJson($full = false, $time_format = 'H:i')
 {
     $json = new stdClass();
     $json->l = $this->tasklist;
     $json->p = $this->parent_id;
     $json->i = $this->indent;
     $json->n = $this->name;
     if ($this->desc) {
         //TODO: Get the proper amount of characters, and cut by last
         //whitespace
         $json->sd = Horde_String::substr($this->desc, 0, 80);
     }
     $json->cp = (bool) $this->completed;
     if ($this->due && ($due = $this->getNextDue())) {
         $json->du = $due->toJson();
     }
     if ($this->start && ($start = $this->getNextStart())) {
         $json->s = $start->toJson();
     }
     $json->pr = (int) $this->priority;
     if ($this->recurs()) {
         $json->r = $this->recurrence->getRecurType();
     }
     $json->t = array_values($this->tags);
     if ($full) {
         // @todo: do we really need all this?
         $json->id = $this->id;
         $json->de = $this->desc;
         if ($this->due) {
             $date = new Horde_Date($this->due);
             $json->dd = $date->strftime('%x');
             $json->dt = $date->format($time_format);
         }
         $json->as = $this->assignee;
         if ($this->estimate) {
             $json->e = $this->estimate;
         }
         /*
         $json->o = $this->owner;
         
         if ($this->completed_date) {
             $date = new Horde_Date($this->completed_date);
             $json->cd = $date->toJson();
         }
         */
         $json->a = (int) $this->alarm;
         $json->m = $this->methods;
         //$json->pv = (boolean)$this->private;
         if ($this->recurs()) {
             $json->r = $this->recurrence->toJson();
         }
         if ($this->tasklist == '**EXTERNAL**') {
             $json->vl = (string) $this->view_link;
             $json->cl = (string) $this->complete_link;
             $json->pe = $json->pd = false;
         } else {
             try {
                 $share = $GLOBALS['nag_shares']->getShare($this->tasklist);
             } catch (Horde_Share_Exception $e) {
                 Horde::log($e->getMessage(), 'ERR');
                 throw new Nag_Exception($e);
             }
             $json->pe = $share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT);
             $json->pd = $share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE);
         }
     }
     return $json;
 }
Пример #10
0
 /**
  * Adds specified EXIF fields to this image's tags.
  * Called during image upload/creation.
  *
  * @param array $fields  An array of EXIF fields to import as a tag.
  *
  * @return void
  */
 protected function _exifToTags(array $fields = array())
 {
     $tags = array();
     foreach ($fields as $field) {
         if (!empty($this->_exif[$field])) {
             if (substr($field, 0, 8) == 'DateTime') {
                 $d = new Horde_Date(strtotime($this->_exif[$field]));
                 $tags[] = $d->format("Y-m-d");
             } elseif ($field == 'Keywords') {
                 $tags = array_merge($tags, explode(',', $this->_exif[$field]));
             } else {
                 $tags[] = $this->_exif[$field];
             }
         }
     }
     $this->_tags = array_merge($this->_tags, $tags);
 }
Пример #11
0
 /**
  * Oh yeah. This is beautiful. Exchange outputs date fields differently in
  * calendar items and emails. We could just always send one or the other,
  * but unfortunately nokia's 'Mail for exchange' depends on this quirk.
  * So we have to send a different date type depending on where it's used.
  * Used when encoding a date value to send to the client.
  *
  * @param Horde_Date $dt  The Horde_Date object to format
  *                        (should normally be in local tz).
  * @param integer $type   The type to format as: One of
  *     TYPE_DATE or TYPE_DATE_DASHES, TYPE_DATE_LOCAL
  *
  * @return string  The formatted date
  * @throws  InvalidArgumentException
  */
 protected function _formatDate(Horde_Date $dt, $type)
 {
     switch ($type) {
         case self::TYPE_DATE:
             return $dt->setTimezone('UTC')->format('Ymd\\THis\\Z');
         case self::TYPE_DATE_DASHES:
             return $dt->setTimezone('UTC')->format('Y-m-d\\TH:i:s\\.000\\Z');
         case self::TYPE_DATE_LOCAL:
             return $dt->format('Y-m-d\\TH:i:s\\.000\\Z');
         default:
             throw new InvalidArgumentException('Unidentified DATE_TYPE');
     }
 }
Пример #12
0
 /**
  * @return string  The time range of the event ("All Day", "1:00pm-3:00pm",
  *                 "08:00-22:00").
  */
 public function getTimeRange()
 {
     if ($this->isAllDay()) {
         return _("All day");
     } elseif (($cmp = $this->start->compareDate($this->end)) > 0) {
         $df = $GLOBALS['prefs']->getValue('date_format');
         if ($cmp > 0) {
             return $this->end->strftime($df) . '-' . $this->start->strftime($df);
         } else {
             return $this->start->strftime($df) . '-' . $this->end->strftime($df);
         }
     } else {
         $twentyFour = $GLOBALS['prefs']->getValue('twentyFour');
         return $this->start->format($twentyFour ? 'G:i' : 'g:ia') . '-' . $this->end->format($twentyFour ? 'G:i' : 'g:ia');
     }
 }
Пример #13
0
        $desc = $event->isPrivate() ? '' : htmlspecialchars($event->description);
        if (strlen($desc)) {
            $desc .= '<br /><br />';
        }
        /* Time. */
        $desc .= _("When:") . ' ' . $event->start->strftime($prefs->getValue('date_format')) . ' ' . $event->start->format($twentyFour ? 'H:i' : 'H:ia') . _(" to ");
        if ($event->start->compareDate($event->end->timestamp()) == 0) {
            $desc .= $event->end->format($twentyFour ? 'H:i' : 'h:ia');
        } else {
            $desc .= $event->end->strftime($prefs->getValue('date_format')) . ' ' . $event->end->format($twentyFor ? 'H:i' : 'h:ia');
        }
        /* Attendees. */
        if (!$event->isPrivate()) {
            $attendees = Kronolith::getAttendeeEmailList($event->attendees);
            if (count($attendees)) {
                $desc .= '<br />' . _("Who:") . ' ' . htmlspecialchars(strval($attendees));
            }
            if (strlen($event->location)) {
                $desc .= '<br />' . _("Where:") . ' ' . htmlspecialchars($event->location);
            }
        }
        $desc .= '<br />' . _("Event Status:") . ' ' . Kronolith::statusToString($event->status);
        $entries[$id]['title'] = htmlspecialchars($event->getTitle());
        $entries[$id]['desc'] = htmlspecialchars($desc);
        $entries[$id]['url'] = htmlspecialchars(Horde::url($event->getViewUrl(), true, -1));
        $entries[$id]['modified'] = $modified->format(DATE_ATOM);
    }
}
$template->set('entries', $entries, true);
$browser->downloadHeaders($calendar . '.xml', 'text/xml', true);
echo $template->fetch(KRONOLITH_TEMPLATES . '/feeds/' . $feed_type . '.xml');
 /**
  * Finds the next recurrence of this event that's after $afterDate.
  *
  * @param Horde_Date|string $after  Return events after this date.
  *
  * @return Horde_Date|boolean  The date of the next recurrence or false
  *                             if the event does not recur after
  *                             $afterDate.
  */
 public function nextRecurrence($after)
 {
     if (!$after instanceof Horde_Date) {
         $after = new Horde_Date($after);
     } else {
         $after = clone $after;
     }
     // Make sure $after and $this->start are in the same TZ
     $after->setTimezone($this->start->timezone);
     if ($this->start->compareDateTime($after) >= 0) {
         return clone $this->start;
     }
     if ($this->recurInterval == 0 && empty($this->rdates)) {
         return false;
     }
     switch ($this->getRecurType()) {
         case self::RECUR_DAILY:
             $diff = $this->start->diff($after);
             $recur = ceil($diff / $this->recurInterval);
             if ($this->recurCount && $recur >= $this->recurCount) {
                 return false;
             }
             $recur *= $this->recurInterval;
             $next = $this->start->add(array('day' => $recur));
             if ((!$this->hasRecurEnd() || $next->compareDateTime($this->recurEnd) <= 0) && $next->compareDateTime($after) >= 0) {
                 return $next;
             }
             break;
         case self::RECUR_WEEKLY:
             if (empty($this->recurData)) {
                 return false;
             }
             $start_week = Horde_Date_Utils::firstDayOfWeek($this->start->format('W'), $this->start->year);
             $start_week->timezone = $this->start->timezone;
             $start_week->hour = $this->start->hour;
             $start_week->min = $this->start->min;
             $start_week->sec = $this->start->sec;
             // Make sure we are not at the ISO-8601 first week of year while
             // still in month 12...OR in the ISO-8601 last week of year while
             // in month 1 and adjust the year accordingly.
             $week = $after->format('W');
             if ($week == 1 && $after->month == 12) {
                 $theYear = $after->year + 1;
             } elseif ($week >= 52 && $after->month == 1) {
                 $theYear = $after->year - 1;
             } else {
                 $theYear = $after->year;
             }
             $after_week = Horde_Date_Utils::firstDayOfWeek($week, $theYear);
             $after_week->timezone = $this->start->timezone;
             $after_week_end = clone $after_week;
             $after_week_end->mday += 7;
             $diff = $start_week->diff($after_week);
             $interval = $this->recurInterval * 7;
             $repeats = floor($diff / $interval);
             if ($diff % $interval < 7) {
                 $recur = $diff;
             } else {
                 /**
                  * If the after_week is not in the first week interval the
                  * search needs to skip ahead a complete interval. The way it is
                  * calculated here means that an event that occurs every second
                  * week on Monday and Wednesday with the event actually starting
                  * on Tuesday or Wednesday will only have one incidence in the
                  * first week.
                  */
                 $recur = $interval * ($repeats + 1);
             }
             if ($this->hasRecurCount()) {
                 $recurrences = 0;
                 /**
                  * Correct the number of recurrences by the number of events
                  * that lay between the start of the start week and the
                  * recurrence start.
                  */
                 $next = clone $start_week;
                 while ($next->compareDateTime($this->start) < 0) {
                     if ($this->recurOnDay((int) pow(2, $next->dayOfWeek()))) {
                         $recurrences--;
                     }
                     ++$next->mday;
                 }
                 if ($repeats > 0) {
                     $weekdays = $this->recurData;
                     $total_recurrences_per_week = 0;
                     while ($weekdays > 0) {
                         if ($weekdays % 2) {
                             $total_recurrences_per_week++;
                         }
                         $weekdays = ($weekdays - $weekdays % 2) / 2;
                     }
                     $recurrences += $total_recurrences_per_week * $repeats;
                 }
             }
             $next = clone $start_week;
             $next->mday += $recur;
             while ($next->compareDateTime($after) < 0 && $next->compareDateTime($after_week_end) < 0) {
                 if ($this->hasRecurCount() && $next->compareDateTime($after) < 0 && $this->recurOnDay((int) pow(2, $next->dayOfWeek()))) {
                     $recurrences++;
                 }
                 ++$next->mday;
             }
             if ($this->hasRecurCount() && $recurrences >= $this->recurCount) {
                 return false;
             }
             if (!$this->hasRecurEnd() || $next->compareDateTime($this->recurEnd) <= 0) {
                 if ($next->compareDateTime($after_week_end) >= 0) {
                     return $this->nextRecurrence($after_week_end);
                 }
                 while (!$this->recurOnDay((int) pow(2, $next->dayOfWeek())) && $next->compareDateTime($after_week_end) < 0) {
                     ++$next->mday;
                 }
                 if (!$this->hasRecurEnd() || $next->compareDateTime($this->recurEnd) <= 0) {
                     if ($next->compareDateTime($after_week_end) >= 0) {
                         return $this->nextRecurrence($after_week_end);
                     } else {
                         return $next;
                     }
                 }
             }
             break;
         case self::RECUR_MONTHLY_DATE:
             $start = clone $this->start;
             if ($after->compareDateTime($start) < 0) {
                 $after = clone $start;
             } else {
                 $after = clone $after;
             }
             // If we're starting past this month's recurrence of the event,
             // look in the next month on the day the event recurs.
             if ($after->mday > $start->mday) {
                 ++$after->month;
                 $after->mday = $start->mday;
             }
             // Adjust $start to be the first match.
             $offset = $after->month - $start->month + ($after->year - $start->year) * 12;
             $offset = floor(($offset + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
             if ($this->recurCount && $offset / $this->recurInterval >= $this->recurCount) {
                 return false;
             }
             $start->month += $offset;
             $count = $offset / $this->recurInterval;
             do {
                 if ($this->recurCount && $count++ >= $this->recurCount) {
                     return false;
                 }
                 // Bail if we've gone past the end of recurrence.
                 if ($this->hasRecurEnd() && $this->recurEnd->compareDateTime($start) < 0) {
                     return false;
                 }
                 if ($start->isValid()) {
                     return $start;
                 }
                 // If the interval is 12, and the date isn't valid, then we
                 // need to see if February 29th is an option. If not, then the
                 // event will _never_ recur, and we need to stop checking to
                 // avoid an infinite loop.
                 if ($this->recurInterval == 12 && ($start->month != 2 || $start->mday > 29)) {
                     return false;
                 }
                 // Add the recurrence interval.
                 $start->month += $this->recurInterval;
             } while (true);
             break;
         case self::RECUR_MONTHLY_WEEKDAY:
             // Start with the start date of the event.
             $estart = clone $this->start;
             // What day of the week, and week of the month, do we recur on?
             if (isset($this->recurNthDay)) {
                 $nth = $this->recurNthDay;
                 $weekday = log($this->recurData, 2);
             } else {
                 $nth = ceil($this->start->mday / 7);
                 $weekday = $estart->dayOfWeek();
             }
             // Adjust $estart to be the first candidate.
             $offset = $after->month - $estart->month + ($after->year - $estart->year) * 12;
             $offset = floor(($offset + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
             // Adjust our working date until it's after $after.
             $estart->month += $offset - $this->recurInterval;
             $count = $offset / $this->recurInterval;
             do {
                 if ($this->recurCount && $count++ >= $this->recurCount) {
                     return false;
                 }
                 $estart->month += $this->recurInterval;
                 $next = clone $estart;
                 $next->setNthWeekday($weekday, $nth);
                 if ($next->compareDateTime($after) < 0) {
                     // We haven't made it past $after yet, try again.
                     continue;
                 }
                 if ($this->hasRecurEnd() && $next->compareDateTime($this->recurEnd) > 0) {
                     // We've gone past the end of recurrence; we can give up
                     // now.
                     return false;
                 }
                 // We have a candidate to return.
                 break;
             } while (true);
             return $next;
         case self::RECUR_YEARLY_DATE:
             // Start with the start date of the event.
             $estart = clone $this->start;
             $after = clone $after;
             if ($after->month > $estart->month || $after->month == $estart->month && $after->mday > $estart->mday) {
                 ++$after->year;
                 $after->month = $estart->month;
                 $after->mday = $estart->mday;
             }
             // Seperate case here for February 29th
             if ($estart->month == 2 && $estart->mday == 29) {
                 while (!Horde_Date_Utils::isLeapYear($after->year)) {
                     ++$after->year;
                 }
             }
             // Adjust $estart to be the first candidate.
             $offset = $after->year - $estart->year;
             if ($offset > 0) {
                 $offset = floor(($offset + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
                 $estart->year += $offset;
             }
             // We've gone past the end of recurrence; give up.
             if ($this->recurCount && $offset >= $this->recurCount) {
                 return false;
             }
             if ($this->hasRecurEnd() && $this->recurEnd->compareDateTime($estart) < 0) {
                 return false;
             }
             return $estart;
         case self::RECUR_YEARLY_DAY:
             // Check count first.
             $dayofyear = $this->start->dayOfYear();
             $count = ($after->year - $this->start->year) / $this->recurInterval + 1;
             if ($this->recurCount && ($count > $this->recurCount || $count == $this->recurCount && $after->dayOfYear() > $dayofyear)) {
                 return false;
             }
             // Start with a rough interval.
             $estart = clone $this->start;
             $estart->year += floor($count - 1) * $this->recurInterval;
             // Now add the difference to the required day of year.
             $estart->mday += $dayofyear - $estart->dayOfYear();
             // Add an interval if the estimation was wrong.
             if ($estart->compareDate($after) < 0) {
                 $estart->year += $this->recurInterval;
                 $estart->mday += $dayofyear - $estart->dayOfYear();
             }
             // We've gone past the end of recurrence; give up.
             if ($this->hasRecurEnd() && $this->recurEnd->compareDateTime($estart) < 0) {
                 return false;
             }
             return $estart;
         case self::RECUR_YEARLY_WEEKDAY:
             // Start with the start date of the event.
             $estart = clone $this->start;
             // What day of the week, and week of the month, do we recur on?
             if (isset($this->recurNthDay)) {
                 $nth = $this->recurNthDay;
                 $weekday = log($this->recurData, 2);
             } else {
                 $nth = ceil($this->start->mday / 7);
                 $weekday = $estart->dayOfWeek();
             }
             // Adjust $estart to be the first candidate.
             $offset = floor(($after->year - $estart->year + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
             // Adjust our working date until it's after $after.
             $estart->year += $offset - $this->recurInterval;
             $count = $offset / $this->recurInterval;
             do {
                 if ($this->recurCount && $count++ >= $this->recurCount) {
                     return false;
                 }
                 $estart->year += $this->recurInterval;
                 $next = clone $estart;
                 $next->setNthWeekday($weekday, $nth);
                 if ($next->compareDateTime($after) < 0) {
                     // We haven't made it past $after yet, try again.
                     continue;
                 }
                 if ($this->hasRecurEnd() && $next->compareDateTime($this->recurEnd) > 0) {
                     // We've gone past the end of recurrence; we can give up
                     // now.
                     return false;
                 }
                 // We have a candidate to return.
                 break;
             } while (true);
             return $next;
     }
     // fall-back to RDATE properties
     if (!empty($this->rdates)) {
         $next = clone $this->start;
         foreach ($this->rdates as $rdate) {
             $next->year = $rdate->year;
             $next->month = $rdate->month;
             $next->mday = $rdate->mday;
             if ($next->compareDateTime($after) > 0) {
                 return $next;
             }
         }
     }
     // We didn't find anything, the recurType was bad, or something else
     // went wrong - return false.
     return false;
 }
Пример #15
0
 /**
  * @throws Nag_Exception
  */
 public function download(Horde_Variables $vars)
 {
     global $display_tasklists, $injector, $registry;
     switch ($vars->actionID) {
         case 'export':
             $tasklists = $vars->get('exportList', $display_tasklists);
             if (!is_array($tasklists)) {
                 $tasklists = array($tasklists);
             }
             /* Get the full, sorted task list. */
             $tasks = Nag::listTasks(array('tasklists' => $tasklists, 'completed' => $vars->exportTasks, 'include_tags' => true, 'include_history' => false));
             $tasks->reset();
             switch ($vars->exportID) {
                 case Horde_Data::EXPORT_CSV:
                     $data = array();
                     while ($task = $tasks->each()) {
                         $task = $task->toHash();
                         $task['desc'] = str_replace(',', '', $task['desc']);
                         $task['tags'] = implode(',', $task['tags']);
                         unset($task['complete_link'], $task['delete_link'], $task['edit_link'], $task['parent'], $task['task_id'], $task['tasklist_id'], $task['view_link'], $task['recurrence'], $task['methods']);
                         foreach (array('start', 'due', 'completed_date') as $field) {
                             if (!empty($task[$field])) {
                                 $date = new Horde_Date($task[$field]);
                                 $task[$field] = $date->format('c');
                             }
                         }
                         $data[] = $task;
                     }
                     $injector->getInstance('Horde_Core_Factory_Data')->create('Csv', array('cleanup' => array($this, 'cleanupData')))->exportFile(_("tasks.csv"), $data, true);
                     exit;
                 case Horde_Data::EXPORT_ICALENDAR:
                     $iCal = new Horde_Icalendar();
                     $iCal->setAttribute('PRODID', '-//The Horde Project//Nag ' . $registry->getVersion() . '//EN');
                     while ($task = $tasks->each()) {
                         $iCal->addComponent($task->toiCalendar($iCal));
                     }
                     return array('data' => $iCal->exportvCalendar(), 'name' => _("tasks.ics"), 'type' => 'text/calendar');
             }
     }
 }
Пример #16
0
 /**
  */
 protected function _content()
 {
     global $prefs;
     if (isset($this->_params['calendar']) && $this->_params['calendar'] != '__all') {
         $calendars = Kronolith::listCalendars();
         if (!isset($calendars[$this->_params['calendar']])) {
             return _("Calendar not found");
         }
         if (!$calendars[$this->_params['calendar']]->hasPermission(Horde_Perms::READ)) {
             return _("Permission Denied");
         }
     }
     $year = date('Y');
     $month = date('m');
     $startday = new Horde_Date(array('mday' => 1, 'month' => $month, 'year' => $year));
     $startday = $startday->dayOfWeek();
     if (!$prefs->getValue('week_start_monday')) {
         $startOfView = 1 - $startday;
         $endday = new Horde_Date(array('mday' => Horde_Date_Utils::daysInMonth($month, $year), 'month' => $month, 'year' => $year));
     } else {
         if ($startday == Horde_Date::DATE_SUNDAY) {
             $startOfView = -5;
         } else {
             $startOfView = 2 - $startday;
         }
     }
     $startDate = new Horde_Date($year, $month, $startOfView);
     $endDate = new Horde_Date($year, $month, Horde_Date_Utils::daysInMonth($month, $year) + 1);
     $endDate->mday += (7 - ($endDate->format('w') - $prefs->getValue('week_start_monday'))) % 7;
     /* Table start. and current month indicator. */
     $html = '<table cellspacing="1" class="monthgrid" width="100%"><tr>';
     /* Set up the weekdays. */
     $weekdays = array(_("Mo"), _("Tu"), _("We"), _("Th"), _("Fr"), _("Sa"));
     if (!$prefs->getValue('week_start_monday')) {
         array_unshift($weekdays, _("Su"));
     } else {
         $weekdays[] = _("Su");
     }
     foreach ($weekdays as $weekday) {
         $html .= '<th class="item">' . $weekday . '</th>';
     }
     try {
         if (isset($this->_params['calendar']) && $this->_params['calendar'] != '__all') {
             list($type, $calendar) = explode('_', $this->_params['calendar'], 2);
             $driver = Kronolith::getDriver($type, $calendar);
             $all_events = $driver->listEvents($startDate, $endDate, array('show_recurrence' => true));
         } else {
             $all_events = Kronolith::listEvents($startDate, $endDate, $GLOBALS['calendar_manager']->get(Kronolith::DISPLAY_CALENDARS));
         }
     } catch (Exception $e) {
         return '<em>' . $e->getMessage() . '</em>';
     }
     $weekday = 0;
     $week = -1;
     $weekStart = $prefs->getValue('week_start_monday');
     for ($date_ob = new Kronolith_Day($month, $startOfView, $year); $date_ob->compareDate($endDate) < 0; $date_ob->mday++) {
         if ($weekday == 7) {
             $weekday = 0;
         }
         if ($weekday == 0) {
             ++$week;
             $html .= '</tr><tr>';
         }
         if ($date_ob->isToday()) {
             $td_class = 'kronolith-today';
         } elseif ($date_ob->month != $month) {
             $td_class = 'kronolith-othermonth';
         } elseif ($date_ob->dayOfWeek() == 0 || $date_ob->dayOfWeek() == 6) {
             $td_class = 'kronolith-weekend';
         } else {
             $td_class = '';
         }
         $html .= '<td align="center" class="' . $td_class . '">';
         /* Set up the link to the day view. */
         $url = Horde::url('day.php', true)->add('date', $date_ob->dateString());
         if (isset($this->_params['calendar']) && $this->_params['calendar'] != '__all') {
             $url->add('display_cal', $this->_params['calendar']);
         }
         $date_stamp = $date_ob->dateString();
         if (empty($all_events[$date_stamp])) {
             /* No events, plain link to the day. */
             $cell = Horde::linkTooltip($url, _("View Day")) . $date_ob->mday . '</a>';
         } else {
             /* There are events; create a cell with tooltip to
              * list them. */
             $day_events = '';
             foreach ($all_events[$date_stamp] as $event) {
                 if ($event->isAllDay()) {
                     $day_events .= _("All day");
                 } else {
                     $day_events .= $event->start->strftime($prefs->getValue('twentyFour') ? '%R' : '%I:%M%p') . '-' . $event->end->strftime($prefs->getValue('twentyFour') ? '%R' : '%I:%M%p');
                 }
                 $location = $event->getLocation();
                 $day_events .= ':' . ($location ? ' (' . htmlspecialchars($location) . ')' : '') . ' ' . $event->getTitle() . "\n";
             }
             $cell = Horde::linkTooltip($url, _("View Day"), '', '', '', $day_events) . $date_ob->mday . '</a>';
         }
         /* Bold the cell if there are events. */
         if (!empty($all_events[$date_stamp])) {
             $cell = '<strong>' . $cell . '</strong>';
         }
         $html .= $cell . '</td>';
         ++$weekday;
     }
     return $html . '</tr></table>';
 }
Пример #17
0
 /**
  * Adds recurrence information to the value hash for SQL
  * INSERT/UPDATE queries.
  *
  * @param array $values  The fields to update.
  * @param array $task    The task information.
  */
 protected function _addRecurrenceFields(&$values, $task)
 {
     if (!$task['recurrence']) {
         $values[] = 0;
         for ($i = 0; $i < 6; $i++) {
             $values[] = null;
         }
     } else {
         $recurrence = $task['recurrence'];
         $recur = $recurrence->getRecurType();
         if ($recurrence->hasRecurEnd()) {
             $recur_end = clone $recurrence->recurEnd;
             $recur_end->setTimezone('UTC');
         } else {
             $recur_end = new Horde_Date(array('year' => 9999, 'month' => 12, 'mday' => 31, 'hour' => 23, 'min' => 59, 'sec' => 59));
         }
         $values[] = $recur;
         $values[] = $recurrence->getRecurInterval();
         $values[] = $recur_end->format('Y-m-d H:i:s');
         $values[] = $recurrence->getRecurCount();
         switch ($recur) {
             case Horde_Date_Recurrence::RECUR_WEEKLY:
                 $values[] = $recurrence->getRecurOnDays();
                 break;
             default:
                 $values[] = null;
                 break;
         }
         $values[] = implode(',', $recurrence->getExceptions());
         $values[] = implode(',', $recurrence->getCompletions());
     }
 }
Пример #18
0
 /**
  * Return the number of hours to offset a POOMCONTACTS:BIRTHDAY
  * or ANNIVERSARY field in an attempt to work around a bug in the
  * protocol - which doesn't define a standard time for birthdays to occur.
  *
  * @param Horde_Date $date  The date.
  * @param boolean $toEas    Convert from local to device if true.
  *
  * @return Horde_Date  The date of the birthday/anniversary, in UTC, with
  *                     any fixes applied for the current device.
  */
 public function normalizePoomContactsDates($date, $toEas = false)
 {
     // WP devices seem to send the birthdays at the entered date, with
     // a time of 00:00:00 UTC.
     //
     // iOS seems different based on version. iOS 5+, at least seems to send
     // the birthday as midnight at the entered date in the device's timezone
     // then converted to UTC. Some minor issues with offsets being off an
     // hour or two for some timezones though.
     //
     // iOS < 5 sends the birthday time part as the time the birthday
     // was entered/edited on the device, converted to UTC, so it can't be
     // trusted at all. The best we can do here is transform the date to
     // midnight on date_default_timezone() converted to UTC.
     //
     // Native Android 4 ALWAYS sends it as 08:00:00 UTC
     //
     // BB 10+ expects it at 12:00:00 UTC
     switch (strtolower($this->clientType)) {
         case self::TYPE_WP:
         case 'wp8':
             // Legacy. Remove in H6.
         // Legacy. Remove in H6.
         case 'wp':
             // Legacy. Remove in H6.
             if ($toEas) {
                 return new Horde_Date($date->format('Y-m-d'), 'UTC');
             } else {
                 return new Horde_Date($date->format('Y-m-d'));
             }
         case self::TYPE_ANDROID:
             if ($this->getMajorVersion() >= 4) {
                 if ($toEas) {
                     return new Horde_Date($date->format('Y-m-d 08:00:00'), 'UTC');
                 } else {
                     return new Horde_Date($date->format('Y-m-d'));
                 }
             } else {
                 // POOMCONTACTS:BIRTHDAY not really supported in early Android
                 // versions. Return as is.
                 return $date;
             }
         case self::TYPE_IPAD:
         case self::TYPE_IPHONE:
         case self::TYPE_IPOD:
             if ($this->getMajorVersion() >= 5) {
                 // iOS >= 5 handles it correctly more or less.
                 return $date;
             } else {
                 if ($toEas) {
                     return new Horde_Date($date->format('Y-m-d'), 'UTC');
                 } else {
                     return new Horde_Date($date->format('Y-m-d'));
                 }
             }
         case self::TYPE_BLACKBERRY:
             if ($toEas) {
                 return new Horde_Date($date->format('Y-m-d 12:00:00'), 'UTC');
             } else {
                 return new Horde_Date($date->format('Y-m-d'));
             }
         case self::TYPE_TOUCHDOWN:
         case self::TYPE_UNKNOWN:
         default:
             return $date;
     }
 }
Пример #19
0
 /**
  * Converts an UTC timestamp like "20061222T110000Z" into a local
  * timestamp like "20061222T130000" using the server timezone.
  *
  * @param array $utc  Array with a datetime string in UTC.
  *
  * @return string  The datetime string converted to the local timezone.
  */
 protected function _convertUTC2LocalTime($utc)
 {
     $date = new Horde_Date($utc[0]);
     $date->setTimezone(date_default_timezone_get());
     return $date->format("Ymd\\THis");
 }
Пример #20
0
 /**
  * Convert an ActiveSync contact message into a hash suitable for
  * importing via self::add().
  *
  * @param Horde_ActiveSync_Message_Contact $message  The contact message
  *                                                   object.
  *
  * @return array  A contact hash.
  */
 public function fromASContact(Horde_ActiveSync_Message_Contact $message)
 {
     $hash = array();
     foreach (self::$_asMap as $turbaField => $asField) {
         if (!$message->isGhosted($asField)) {
             try {
                 $hash[$turbaField] = $message->{$asField};
             } catch (InvalidArgumentException $e) {
             }
         }
     }
     /* Requires special handling */
     try {
         if ($message->getProtocolVersion() >= Horde_ActiveSync::VERSION_TWELVE) {
             if (!empty($message->airsyncbasebody)) {
                 $hash['notes'] = $message->airsyncbasebody->data;
             }
         } else {
             $hash['notes'] = $message->body;
         }
     } catch (InvalidArgumentException $e) {
     }
     // picture ($message->picture *should* already be base64 encdoed)
     if (!$message->isGhosted('picture')) {
         $hash['photo'] = base64_decode($message->picture);
     }
     /* Email addresses */
     $hash['emails'] = array();
     if (!$message->isGhosted('email1address')) {
         $e = Horde_Icalendar_Vcard::getBareEmail($message->email1address);
         $hash['emails'][] = $hash['email'] = $e ? $e : '';
     }
     if (!$message->isGhosted('email2address')) {
         $e = Horde_Icalendar_Vcard::getBareEmail($message->email2address);
         $hash['emails'][] = $hash['homeEmail'] = $e ? $e : '';
     }
     if (!$message->isGhosted('email3address')) {
         $e = Horde_Icalendar_Vcard::getBareEmail($message->email3address);
         $hash['emails'][] = $hash['workEmail'] = $e ? $e : '';
     }
     $hash['emails'] = implode(',', $hash['emails']);
     /* Categories */
     if (is_array($message->categories) && count($message->categories)) {
         $hash['__tags'] = $message->categories;
     }
     /* Children */
     if (is_array($message->children) && count($message->children)) {
         // We use a comma as incoming delimiter as it's the most
         // common even though it might be used withing a name string.
         $hash['children'] = implode(', ', $message->children);
     } elseif (!$message->isGhosted('children')) {
         $hash['children'] = '';
     }
     /* Birthday and Anniversary */
     if (!empty($message->birthday)) {
         $bday = new Horde_Date($message->birthday);
         $bday->setTimezone(date_default_timezone_get());
         $hash['birthday'] = $bday->format('Y-m-d');
     } elseif (!$message->isGhosted('birthday')) {
         $hash['birthday'] = '';
     }
     if (!empty($message->anniversary)) {
         $anniversary = new Horde_Date($message->anniversary);
         $anniversary->setTimezone(date_default_timezone_get());
         $hash['anniversary'] = $anniversary->format('Y-m-d');
     } elseif (!$message->isGhosted('anniversary')) {
         $hash['anniversary'] = '';
     }
     /* Countries */
     include 'Horde/Nls/Countries.php';
     if (!empty($message->homecountry)) {
         if (!empty($this->map['homeCountryFree'])) {
             $hash['homeCountryFree'] = $message->homecountry;
         } else {
             $country = array_search($message->homecountry, $countries);
             if ($country === false) {
                 $country = $message->homecountry;
             }
             $hash['homeCountry'] = $country;
         }
     } elseif (!$message->isGhosted('homecountry')) {
         $hash['homeCountry'] = '';
     }
     if (!empty($message->businesscountry)) {
         if (!empty($this->map['workCountryFree'])) {
             $hash['workCountryFree'] = $message->businesscountry;
         } else {
             $country = array_search($message->businesscountry, $countries);
             if ($country === false) {
                 $country = $message->businesscountry;
             }
             $hash['workCountry'] = $country;
         }
     } elseif (!$message->isGhosted('businesscountry')) {
         $hash['workCountry'] = '';
     }
     if (!empty($message->othercountry)) {
         if (!empty($this->map['otherCountryFree'])) {
             $hash['otherCountryFree'] = $message->othercountry;
         } else {
             $country = array_search($message->othercountry, $countries);
             if ($country === false) {
                 $country = $message->othercountry;
             }
             $hash['otherCountry'] = $country;
         }
     } elseif (!$message->isGhosted('othercountry')) {
         $hash['otherCountry'] = '';
     }
     return $hash;
 }
Пример #21
0
 public function UTC2LocalDate($s)
 {
     $date = new Horde_Date($s);
     $date->setTimezone(date_default_timezone_get());
     return $date->format('Ymd') . 'T000000';
 }
Пример #22
0
 /**
  * Adds rules from this ruleset to a VTIMEZONE component.
  *
  * @param Horde_Icalendar_Vtimezone $tz  A VTIMEZONE component.
  * @param string $tzid                   The timezone ID of the component.
  * @param string $name                   A timezone name abbreviation.
  *                                       May contain a placeholder that is
  *                                       replaced the Rules' "Letter(s)"
  *                                       entry.
  * @param array $startOffset             An offset hash describing the
  *                                       base offset of a timezone.
  * @param Horde_Date $start              Start of the period to add rules
  *                                       for.
  * @param Horde_Date $end                End of the period to add rules
  *                                       for.
  */
 public function addRules(Horde_Icalendar_Vtimezone $tz, $tzid, $name, $startOffset, Horde_Date $start, Horde_Date $end = null)
 {
     $offset = $startOffset;
     foreach ($this->_rules as $rule) {
         $year = $rule[3];
         if ($year[0] == 'o') {
             // TO is "only"
             $rule[3] = $rule[2];
         }
         if ($rule[3][0] != 'm' && $rule[3] < $start->year) {
             // TO is not maximum and is before the searched period
             continue;
         }
         if ($end && $rule[2][0] != 'm' && $rule[2] > $end->year) {
             // FROM is not "minimum" and is after the searched period
             break;
         }
         if ($rule[2][0] != 'm' && $rule[2] < $start->year) {
             $rule[2] = $start->year;
         }
         if ($rule[8] == 0) {
             $component = new Horde_Icalendar_Standard();
             $component->setAttribute('TZOFFSETFROM', $offset);
             $component->setAttribute('TZOFFSETTO', $startOffset);
             $offset = $startOffset;
         } else {
             $component = new Horde_Icalendar_Daylight();
             $component->setAttribute('TZOFFSETFROM', $offset);
             $offset = $this->_getOffset($startOffset, $rule[8]);
             $component->setAttribute('TZOFFSETTO', $offset);
         }
         $month = Horde_Timezone::getMonth($rule[5]);
         // Retrieve time of rule start.
         preg_match('/(\\d+)(?::(\\d+))?(?::(\\d+))?(w|s|u)?/', $rule[7], $match);
         if (!isset($match[2])) {
             $match[2] = 0;
         }
         if ($rule[2] == $rule[3] && preg_match('/^\\d+$/', $rule[6])) {
             // Rule lasts only for a single year and starts on a specific
             // date.
             $rdate = new Horde_Date(array('year' => $rule[2], 'month' => Horde_Timezone::getMonth($rule[5]), 'mday' => $rule[6], 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             $component->setAttribute('DTSTART', $rdate);
         } elseif (substr($rule[6], 0, 4) == 'last') {
             // Rule starts on the last of a certain weekday of the month.
             $weekday = $this->_weekdays[substr($rule[6], 4, 3)];
             $last = new Horde_Date(array('year' => $rule[2], 'month' => $month, 'mday' => Horde_Date_Utils::daysInMonth($month, $rule[2]), 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             while ($last->dayOfWeek() != $weekday) {
                 $last->mday--;
             }
             $component->setAttribute('DTSTART', $last);
             if ($rule[3][0] == 'm') {
                 $until = '';
             } else {
                 $last = new Horde_Date(array('year' => $rule[3], 'month' => $month, 'mday' => Horde_Date_Utils::daysInMonth($month, $rule[2]), 'hour' => $match[1], 'min' => $match[2], 'sec' => 0), $tzid);
                 while ($last->dayOfWeek() != $weekday) {
                     $last->mday--;
                 }
                 $last->setTimezone('UTC');
                 $until = ';UNTIL=' . $last->format('Ymd\\THIs') . 'Z';
             }
             $component->setAttribute('RRULE', 'FREQ=YEARLY;BYDAY=-1' . Horde_String::upper(substr($rule[6], 4, 2)) . ';BYMONTH=' . $month . $until);
         } elseif (strpos($rule[6], '>=')) {
             // Rule starts on a certain weekday after a certain day of
             // month.
             list($weekday, $day) = explode('>=', $rule[6]);
             $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)];
             $first = new Horde_Date(array('year' => $rule[2], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             while ($first->dayOfWeek() != $weekdayInt) {
                 $first->mday++;
             }
             $component->setAttribute('DTSTART', $first);
             if ($rule[3][0] == 'm') {
                 $until = '';
             } else {
                 $last = new Horde_Date(array('year' => $rule[3], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0), $tzid);
                 while ($last->dayOfWeek() != $weekday) {
                     $last->mday++;
                 }
                 $last->setTimezone('UTC');
                 $until = ';UNTIL=' . $last->format('Ymd\\THIs') . 'Z';
             }
             for ($days = array(), $i = $day, $lastDay = min(Horde_Date_Utils::daysInMonth($month, $rule[2]), $i + 6); $day > 1 && $i <= $lastDay; $i++) {
                 $days[] = $i;
             }
             $component->setAttribute('RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ($days ? ';BYMONTHDAY=' . implode(',', $days) : '') . ';BYDAY=1' . Horde_String::upper(substr($weekday, 0, 2)) . $until);
         } elseif (strpos($rule[6], '<=')) {
             // Rule starts on a certain weekday before a certain day of
             // month.
             list($weekday, $day) = explode('>=', $rule[6]);
             $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)];
             $last = new Horde_Date(array('year' => $rule[2], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             while ($last->dayOfWeek() != $weekdayInt) {
                 $last->mday--;
             }
             $component->setAttribute('DTSTART', $last);
             if ($rule[3][0] == 'm') {
                 $until = '';
             } else {
                 $last = new Horde_Date(array('year' => $rule[3], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0), $tzid);
                 while ($last->dayOfWeek() != $weekday) {
                     $last->mday--;
                 }
                 $last->setTimezone('UTC');
                 $until = ';UNTIL=' . $last->format('Ymd\\THIs') . 'Z';
             }
             for ($days = array(), $i = 1; $i <= $day; $i++) {
                 $days[] = $i;
             }
             $component->setAttribute('RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ';BYMONTHDAY=' . implode(',', $days) . ';BYDAY=-1' . Horde_String::upper(substr($weekday, 0, 2)) . $until);
         }
         $component->setAttribute('TZNAME', sprintf($name, $rule[9]));
         $tz->addComponent($component);
     }
 }
Пример #23
0
 /**
  * Deletes an event identified by UID.
  *
  * @param string|array $uid     A single UID or an array identifying the
  *                              event(s) to delete.
  *
  * @param string $recurrenceId  The reccurenceId for the event instance, if
  *                              this is a deletion of a recurring event
  *                              instance ($uid must not be an array).
  * @param string $range         The range value if deleting a recurring
  *                              event instance. Only supported values are
  *                              null or Kronolith::RANGE_THISANDFUTURE.
  *                              @since 4.1.5
  *
  * @throws Kronolith_Exception
  */
 public function delete($uid, $recurrenceId = null, $range = null)
 {
     // Handle an array of UIDs for convenience of deleting multiple events
     // at once.
     if (is_array($uid)) {
         foreach ($uid as $g) {
             $this->delete($g);
         }
         return;
     }
     $kronolith_driver = Kronolith::getDriver();
     $events = $kronolith_driver->getByUID($uid, null, true);
     $event = null;
     // First try the user's own calendars.
     if (empty($event)) {
         $ownerCalendars = Kronolith::listInternalCalendars(true, Horde_Perms::DELETE);
         foreach ($events as $ev) {
             if (isset($ownerCalendars[$ev->calendar])) {
                 $kronolith_driver->open($ev->calendar);
                 $event = $ev;
                 break;
             }
         }
     }
     // If not successful, try all calendars the user has access to.
     if (empty($event)) {
         $deletableCalendars = Kronolith::listInternalCalendars(false, Horde_Perms::DELETE);
         foreach ($events as $ev) {
             if (isset($deletableCalendars[$ev->calendar])) {
                 $kronolith_driver->open($ev->calendar);
                 $event = $ev;
                 break;
             }
         }
     }
     // Are we an admin cleaing up user data?
     if (empty($event) && $GLOBALS['registry']->isAdmin()) {
         $event = $events[0];
     }
     if (empty($event)) {
         throw new Horde_Exception_PermissionDenied();
     }
     if ($recurrenceId && $event->recurs() && empty($range)) {
         $deleteDate = new Horde_Date($recurrenceId);
         $event->recurrence->addException($deleteDate->format('Y'), $deleteDate->format('m'), $deleteDate->format('d'));
         $event->save();
     } elseif ($range == Kronolith::RANGE_THISANDFUTURE) {
         // Deleting the instance and remaining series.
         $instance = new Horde_Date($recurrenceId);
         $recurEnd = clone $instance;
         $recurEnd->mday--;
         if ($event->end->compareDate($recurEnd) > 0) {
             $kronolith_driver->deleteEvent($event->id);
         } else {
             $event->recurrence->setRecurEnd($recurEnd);
             $result = $event->save();
         }
     } elseif ($recurrenceId) {
         throw new Kronolith_Exception(_("Unable to delete event. An exception date was provided but the event does not seem to be recurring."));
     } else {
         $kronolith_driver->deleteEvent($event->id);
     }
 }
Пример #24
0
 public function vevent2sif($vcard)
 {
     /* Some special handling for all-day vEvents that are not passed
      * as TYPE=DATE (TYPE=DATE does not exist for vCalendar 1.0) */
     if (preg_match('/(\\r\\n|\\r|\\n)DTSTART:.*T000000(\\r\\n|\\r|\\n)/', $vcard)) {
         if (preg_match('/(\\r\\n|\\r|\\n)DTEND:(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T235959(\\r\\n|\\r|\\n)/', $vcard, $m)) {
             $vcard = preg_replace('/(\\r\\n|\\r|\\n)DTSTART:(.*)T000000(\\r\\n|\\r|\\n)/', "\$1DTSTART;VALUE=DATE:\$2\$3", $vcard);
             $vcard = preg_replace('/(\\r\\n|\\r|\\n)DTEND:(.*)T235959(\\r\\n|\\r|\\n)/', "\$1DTEND;VALUE=DATE:\$2\$3", $vcard);
         }
         // @TODO: else: handle case with DTEND= T240000
     }
     $iCal = new Horde_Icalendar();
     if (!$iCal->parsevCalendar($vcard)) {
         // @TODO: NEVER use die() in a library.
         die("There was an error importing the data.");
     }
     $components = $iCal->getComponents();
     switch (count($components)) {
         case 0:
             // @TODO: NEVER use die() in a library.
             die("No data was found.");
         case 1:
             $content = $components[0];
             break;
         default:
             // @TODO: NEVER use die() in a library.
             die("Multiple components found; only one is supported.");
     }
     $hash = array('ReminderSet' => 0, 'IsRecurring' => 0, 'BusyStatus' => 2);
     $alarm = $end = null;
     $start = $content->getAttribute('DTSTART');
     $start_params = $content->getAttribute('DTSTART', true);
     if (!empty($start_params[0]['VALUE']) && $start_params[0]['VALUE'] == 'DATE') {
         $hash['AllDayEvent'] = 1;
         $hash['Start'] = sprintf('%04d-%02d-%02d', $start['year'], $start['month'], $start['mday']);
         $start = mktime(0, 0, 0, $start['month'], $start['mday'], $start['year']);
     } else {
         $hash['AllDayEvent'] = 0;
         $hash['Start'] = Horde_Icalendar::_exportDateTime($start);
     }
     foreach ($content->getAllAttributes() as $item) {
         $GLOBALS['backend']->logMessage(sprintf('Sync4j for name %s, value %s', $item['name'], is_string($item['value']) ? $item['value'] : var_export($item['value'], true)), 'DEBUG');
         switch (Horde_String::upper($item['name'])) {
             case 'DTSTART':
                 break;
             case 'DTEND':
                 if (!empty($item['params']['VALUE']) && $item['params']['VALUE'] == 'DATE') {
                     $hash['AllDayEvent'] = 1;
                     $date = new Horde_Date($item['value']['year'], $item['value']['month'], $item['value']['mday']);
                     $date->mday--;
                     $hash['End'] = $date->format('Y-m-d');
                     $end = $date->datestamp();
                 } else {
                     $hash['AllDayEvent'] = 0;
                     $hash['End'] = Horde_Icalendar::_exportDateTime($item['value']);
                     $end = $item['value'];
                 }
                 break;
             case 'SUMMARY':
                 $hash['Subject'] = $item['value'];
                 break;
             case 'DESCRIPTION':
                 $hash['Body'] = $item['value'];
                 break;
             case 'LOCATION':
                 $hash['Location'] = $item['value'];
                 break;
             case 'CATEGORIES':
                 $hash['Categories'] = $item['value'];
                 break;
             case 'AALARM':
                 $hash['ReminderSet'] = 1;
                 $alarm = $item['value'];
                 break;
             case 'STATUS':
                 switch (Horde_String::upper($item['value'])) {
                     case 'FREE':
                     case 'CANCELLED':
                         $hash['BusyStatus'] = 0;
                         break;
                     case 'TENTATIVE':
                         $hash['BusyStatus'] = 1;
                         break;
                     case 'CONFIRMED':
                         $hash['BusyStatus'] = 2;
                         break;
                 }
                 break;
             case 'CLASS':
                 switch (Horde_String::upper($item['value'])) {
                     case 'PUBLIC':
                         $hash['Sensitivity'] = 0;
                         break;
                     case 'PRIVATE':
                         $hash['Sensitivity'] = 2;
                         break;
                     case 'CONFIDENTIAL':
                         $hash['Sensitivity'] = 3;
                         break;
                 }
                 break;
             case 'RRULE':
                 // Parse the recurrence rule into keys and values.
                 $rdata = array();
                 $parts = explode(';', $item['value']);
                 foreach ($parts as $part) {
                     list($key, $value) = explode('=', $part, 2);
                     $rdata[Horde_String::upper($key)] = $value;
                 }
                 if (!isset($rdata['FREQ'])) {
                     break;
                 }
                 $hash['IsRecurring'] = 1;
                 if (isset($rdata['BYDAY'])) {
                     $maskdays = array('SU' => Horde_Date::MASK_SUNDAY, 'MO' => Horde_Date::MASK_MONDAY, 'TU' => Horde_Date::MASK_TUESDAY, 'WE' => Horde_Date::MASK_WEDNESDAY, 'TH' => Horde_Date::MASK_THURSDAY, 'FR' => Horde_Date::MASK_FRIDAY, 'SA' => Horde_Date::MASK_SATURDAY);
                     $days = explode(',', $rdata['BYDAY']);
                     $mask = 0;
                     foreach ($days as $day) {
                         $instance = (int) $day;
                         $mask |= $maskdays[str_replace($instance, '', $day)];
                     }
                 }
                 $hash['Interval'] = isset($rdata['INTERVAL']) ? $rdata['INTERVAL'] : 1;
                 switch (Horde_String::upper($rdata['FREQ'])) {
                     case 'DAILY':
                         $hash['RecurrenceType'] = 0;
                         break;
                     case 'WEEKLY':
                         $hash['RecurrenceType'] = 1;
                         if (isset($rdata['BYDAY'])) {
                             $hash['DayOfWeekMask'] = $mask;
                         }
                         break;
                     case 'MONTHLY':
                         if (isset($rdata['BYDAY'])) {
                             $hash['RecurrenceType'] = 3;
                             $hash['Instance'] = $instance;
                             $hash['DayOfWeekMask'] = $mask;
                         } else {
                             $hash['RecurrenceType'] = 2;
                             $hash['DayOfMonth'] = date('j', $start);
                         }
                         break;
                     case 'YEARLY':
                         if (isset($rdata['BYDAY'])) {
                             $hash['RecurrenceType'] = 6;
                             $hash['Instance'] = $instance;
                             $hash['DayOfWeekMask'] = $mask;
                         } else {
                             $hash['RecurrenceType'] = 5;
                             $hash['DayOfMonth'] = date('j', $start);
                         }
                         $hash['MonthOfYear'] = date('n', $start);
                         unset($hash['Interval']);
                         break;
                 }
                 if (isset($rdata['UNTIL'])) {
                     $hash['NoEndDate'] = 0;
                     $hash['PatternEndDate'] = $rdata['UNTIL'];
                 } elseif (isset($rdata['COUNT'])) {
                     $hash['NoEndDate'] = 0;
                     $hash['Occurrences'] = $rdata['COUNT'];
                 } else {
                     $hash['NoEndDate'] = 1;
                 }
                 break;
             case 'EXDATE':
                 if (empty($hash['Exceptions'])) {
                     $hash['Exceptions'] = array();
                 }
                 foreach ($item['values'] as $date) {
                     if ($hash['AllDayEvent'] == 1) {
                         $d = new Horde_Date(array('year' => $date['year'], 'month' => $date['month'], 'mday' => $date['mday'] + 1));
                         $hash['Exceptions'][] = array('ExcludeDate' => $d->format('Y-m-d'));
                     } else {
                         $hash['Exceptions'][] = array('ExcludeDate' => Horde_Icalendar::_exportDate($date));
                     }
                 }
                 break;
         }
     }
     if (!empty($start)) {
         if ($hash['ReminderSet'] && !empty($alarm) && $start != $alarm) {
             $hash['ReminderMinutesBeforeStart'] = ($start - $alarm) / 60;
         } else {
             // Parse VALARM components.
             foreach ($content->getComponents() as $component) {
                 if ($component->getType() != 'vAlarm') {
                     continue;
                 }
                 try {
                     $trigger = $component->getAttribute('TRIGGER');
                 } catch (Horde_Icalendar_Exception $e) {
                     continue;
                 }
                 if (is_array($trigger) || empty($trigger)) {
                     continue;
                 }
                 $hash['ReminderSet'] = 1;
                 $hash['ReminderMinutesBeforeStart'] = -$trigger / 60;
             }
         }
     }
     if (empty($hash['AllDayEvent']) && !empty($start) && !empty($end) && $start != $end) {
         $hash['Duration'] = ($end - $start) / 60;
         $GLOBALS['backend']->logMessage('Duration set to ' . $hash['Duration'], 'DEBUG');
     }
     return Horde_SyncMl_Device_sync4j::array2sif($hash, '<?xml version="1.0"?><appointment>', '</appointment>');
 }
Пример #25
0
 /**
  * Lists all events in the given time range.
  *
  * @param Horde_Date $startDate Start of range date object.
  * @param Horde_Date $endDate   End of range data object.
  *
  * @return array Events in the given time range.
  *
  * @throws Horde_Kolab_FreeBusy_Exception If retrieving the events failed.
  */
 public function listEvents(Horde_Date $startDate, Horde_Date $endDate)
 {
     $url = $this->_params['url'] . '/public/?cmd=freebusy' . '&start=' . $startDate->format('c') . '&end=' . $endDate->format('c') . '&interval=' . $this->_params['interval'] . '&u=SMTP:' . $this->_owner->getOwner();
     $response = $this->_client->get($url, array('User-Agent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)'));
     if ($response->code !== 200) {
         throw new Horde_Kolab_FreeBusy_Exception_NotFound(sprintf('Unable to fetch free/busy information from %s', $url));
     }
     $owa = new Horde_Kolab_FreeBusy_Freebusy_Helper_Owa($response->getStream());
     $result = $owa->convert($startDate, $endDate, $this->_params['interval']);
     if (!isset($result[$this->_owner->getOwner()])) {
         return array();
     }
     $events = array();
     foreach ($result[$this->_owner->getOwner()] as $item) {
         $events[] = new Horde_Kolab_FreeBusy_Object_Event($item);
     }
     return $events;
 }
Пример #26
0
 protected function _fqlToTurba($fields, $result)
 {
     //$remove = array();
     foreach ($fields as $field) {
         if (strpos($field, '.') !== false) {
             $key = substr($field, 0, strpos($field, '.'));
             $subfield = substr($field, strpos($field, '.') + 1);
             $result[$field] = $result[$key][$subfield];
         }
     }
     if (!empty($result['birthday_date'])) {
         // Make sure the birthdate is in a standard format that
         // listDateObjects will understand.
         $bday = new Horde_Date($result['birthday_date']);
         $result['birthday_date'] = $bday->format('Y-m-d');
     }
     return $result;
 }
Пример #27
0
 /**
  * Prepares this event to be saved to the backend.
  *
  * @param boolean $full  Return full data, including uid and id.
  *
  * @return array  The event properties.
  */
 public function toProperties($full = false)
 {
     $driver = $this->getDriver();
     $properties = array();
     if ($full) {
         $properties['event_id'] = $this->id;
         $properties['event_uid'] = $this->uid;
     }
     /* Basic fields. */
     $properties['event_creator_id'] = $driver->convertToDriver($this->creator);
     $properties['event_title'] = $driver->convertToDriver($this->title);
     $properties['event_description'] = $driver->convertToDriver($this->description);
     $properties['event_location'] = $driver->convertToDriver($this->location);
     $properties['event_timezone'] = $this->timezone;
     $properties['event_url'] = (string) $this->url;
     $properties['event_private'] = (int) $this->private;
     $properties['event_status'] = $this->status;
     $properties['event_attendees'] = serialize($this->attendees);
     $properties['event_resources'] = serialize($driver->convertToDriver($this->getResources()));
     $properties['event_modified'] = $_SERVER['REQUEST_TIME'];
     $properties['event_organizer'] = $this->organizer;
     if ($this->isAllDay()) {
         $properties['event_start'] = $this->start->strftime('%Y-%m-%d %H:%M:%S');
         $properties['event_end'] = $this->end->strftime('%Y-%m-%d %H:%M:%S');
         $properties['event_allday'] = 1;
     } else {
         if ($driver->getParam('utc')) {
             $start = clone $this->start;
             $end = clone $this->end;
             $start->setTimezone('UTC');
             $end->setTimezone('UTC');
         } else {
             $start = $this->start;
             $end = $this->end;
         }
         $properties['event_start'] = $start->strftime('%Y-%m-%d %H:%M:%S');
         $properties['event_end'] = $end->strftime('%Y-%m-%d %H:%M:%S');
         $properties['event_allday'] = 0;
     }
     /* Alarm. */
     $properties['event_alarm'] = (int) $this->alarm;
     /* Alarm Notification Methods. */
     $properties['event_alarm_methods'] = serialize($driver->convertToDriver($this->methods));
     /* Recurrence. */
     if (!$this->recurs()) {
         $properties['event_recurtype'] = 0;
     } else {
         $recur = $this->recurrence->getRecurType();
         if ($this->recurrence->hasRecurEnd()) {
             if ($driver->getParam('utc')) {
                 $recur_end = clone $this->recurrence->recurEnd;
                 $recur_end->setTimezone('UTC');
             } else {
                 $recur_end = $this->recurrence->recurEnd;
             }
         } else {
             $recur_end = new Horde_Date(array('year' => 9999, 'month' => 12, 'mday' => 31, 'hour' => 23, 'min' => 59, 'sec' => 59));
         }
         $properties['event_recurtype'] = $recur;
         $properties['event_recurinterval'] = $this->recurrence->getRecurInterval();
         $properties['event_recurenddate'] = $recur_end->format('Y-m-d H:i:s');
         $properties['event_recurcount'] = $this->recurrence->getRecurCount();
         switch ($recur) {
             case Horde_Date_Recurrence::RECUR_WEEKLY:
                 $properties['event_recurdays'] = $this->recurrence->getRecurOnDays();
                 break;
         }
         $properties['event_exceptions'] = implode(',', $this->recurrence->getExceptions());
     }
     /* Exception information */
     if (!empty($this->baseid)) {
         $properties['event_baseid'] = $this->baseid;
         if ($driver->getParam('utc')) {
             $eod = clone $this->exceptionoriginaldate;
             $eod->setTimezone('UTC');
         } else {
             $eod = $this->exceptionoriginaldate;
         }
         $properties['event_exceptionoriginaldate'] = $eod->strftime('%Y-%m-%d %H:%M:%S');
     } else {
         /* This must be an empty string. */
         $properties['event_baseid'] = '';
         $properties['event_exceptionoriginaldate'] = null;
     }
     return $properties;
 }