Merges results from two listEvents() result sets.
public static mergeEvents ( array &$results, array $events ) | ||
$results | array | First list of events. |
$events | array | List of events to be merged into the first one. |
/** * Returns the ids of all the events that happen within a time period. * Only includes recurring events once per time period, and does not include * events that represent exceptions, making this method useful for syncing * purposes. For more control, use the listEvents method. * * @param string|array $calendars The calendar to check for events. * @param object $startstamp The start of the time range. * @param object $endstamp The end of the time range. * * @return array The event ids happening in this time period. * @throws Kronolith_Exception */ public function listUids($calendars = null, $startstamp = 0, $endstamp = 0) { if (empty($calendars)) { $calendars = Kronolith::getSyncCalendars(); } elseif (!is_array($calendars)) { $calendars = array($calendars); } $driver = Kronolith::getDriver(); $results = array(); foreach ($calendars as $calendar) { if (!Kronolith::hasPermission($calendar, Horde_Perms::READ)) { Horde::log(sprintf(_("Permission Denied or Calendar Not Found: %s - skipping."), $calendar)); continue; } try { $driver->open($calendar); $events = $driver->listEvents($startstamp ? new Horde_Date($startstamp) : null, $endstamp ? new Horde_Date($endstamp) : null, array('cover_dates' => false, 'hide_exceptions' => true)); Kronolith::mergeEvents($results, $events); } catch (Kronolith_Exception $e) { Horde::log($e); } } $uids = array(); foreach ($results as $dayevents) { foreach ($dayevents as $event) { $uids[] = $event->uid; } } return $uids; }
/** * Saves an event and returns a signed result object including the saved * event. * * @param Kronolith_Event $event An event object. * @param Kronolith_Event $original If $event is an exception, this should * be set to the original event. * @param object $attributes The attributes sent by the client. * Expected to contain cstart and cend. * @param boolean $saveOriginal Commit any changes in $original to * storage also. * * @return object The result object. */ protected function _saveEvent(Kronolith_Event $event, Kronolith_Event $original = null, $attributes = null, $saveOriginal = false) { if ($this->vars->targetcalendar) { $cal = $this->vars->targetcalendar; } elseif ($this->vars->cal) { $cal = $this->vars->cal; } else { $cal = $event->calendarType . '|' . $event->calendar; } $result = $this->_signedResponse($cal); $events = array(); try { $event->save(); if (!$this->vars->view_start || !$this->vars->view_end) { $result->events = array(); return $result; } $end = new Horde_Date($this->vars->view_end); $end->hour = 23; $end->min = $end->sec = 59; Kronolith::addEvents($events, $event, new Horde_Date($this->vars->view_start), $end, true, true); // If this is an exception, we re-add the original event also; // cstart and cend are the cacheStart and cacheEnd dates from the // client. if (!empty($original)) { Kronolith::addEvents($events, $original, new Horde_Date($attributes->cstart), new Horde_Date($attributes->cend), true, true); if ($saveOriginal) { $original->save(); } } // If this event recurs, we must add any bound exceptions to the // results if ($event->recurs()) { $bound = $event->boundExceptions(false); foreach ($bound as $day => &$exceptions) { foreach ($exceptions as &$exception) { $exception = $exception->toJson(); } } Kronolith::mergeEvents($events, $bound); } $result->events = count($events) ? $events : array(); } catch (Exception $e) { $GLOBALS['notification']->push($e, 'horde.error'); } return $result; }
/** * Generates the free/busy text for $calendars. * * @param string|array $calendars The calendar to view free/busy slots for. * @param integer $startstamp The start of the time period to retrieve. * @param integer $endstamp The end of the time period to retrieve. * @param boolean $returnObj Default false. Return a vFreebusy object * instead of text. * @param string $user Set organizer to this user. * * @return string The free/busy text. * @throws Horde_Exception, Kronolith_Exception */ public static function generate($calendars, $startstamp = null, $endstamp = null, $returnObj = false, $user = null) { if (!is_array($calendars)) { $calendars = array($calendars); } if (!$user) { $kronolith_shares = $GLOBALS['injector']->getInstance('Kronolith_Shares'); /* Find a share and retrieve owner. */ foreach ($calendars as $calendar) { if (strpos($calendar, 'internal_') !== 0) { continue; } $calendar = substr($calendar, 9); try { $share = $kronolith_shares->getShare($calendar); $user = $share->get('owner'); break; } catch (Horde_Exception $e) { } } } /* Default the start date to today. */ if (is_null($startstamp)) { $startstamp = mktime(0, 0, 0); } /* Default the end date to the start date + freebusy_days. */ if (is_null($endstamp) || $endstamp < $startstamp) { $enddate = new Horde_Date($startstamp); $enddate->mday += $GLOBALS['prefs']->getValue('freebusy_days'); $endstamp = $enddate->timestamp(); } else { $enddate = new Horde_Date($endstamp); } /* Get the Identity for the owner of the share. */ $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($user); $email = $identity->getValue('from_addr'); $cn = $identity->getValue('fullname'); if (empty($email) && empty($cn)) { $cn = $user; } /* Fetch events. */ $busy = array(); foreach ($calendars as $calendar) { if (strpos($calendar, '_')) { @(list($type, $calendar) = explode('_', $calendar, 2)); } else { $type = 'internal'; } try { $GLOBALS['injector']->getInstance('Kronolith_Shares')->getShare($calendar); } catch (Horde_Exception $e) { throw new Kronolith_Exception('Share not found.'); } try { $driver = Kronolith::getDriver($type, $calendar); $events = $driver->listEvents(new Horde_Date($startstamp), $enddate, array('show_recurrence' => true)); Kronolith::mergeEvents($busy, $events); } catch (Exception $e) { } } /* Create the new iCalendar. */ $vCal = new Horde_Icalendar(); $vCal->setAttribute('PRODID', '-//The Horde Project//Kronolith ' . $GLOBALS['registry']->getVersion() . '//EN'); $vCal->setAttribute('METHOD', 'PUBLISH'); /* Create new vFreebusy. */ $vFb = Horde_Icalendar::newComponent('vfreebusy', $vCal); $params = array(); if (!empty($cn)) { $params['CN'] = $cn; } if (!empty($email)) { $vFb->setAttribute('ORGANIZER', 'mailto:' . $email, $params); } else { $vFb->setAttribute('ORGANIZER', '', $params); } $vFb->setAttribute('DTSTAMP', $_SERVER['REQUEST_TIME']); $vFb->setAttribute('DTSTART', $startstamp); $vFb->setAttribute('DTEND', $endstamp); $vFb->setAttribute('URL', Horde::url('fb.php?u=' . $user, true, -1)); /* Add all the busy periods. */ foreach ($busy as $events) { foreach ($events as $event) { if ($event->status == Kronolith::STATUS_FREE) { continue; } if ($event->status == Kronolith::STATUS_CANCELLED) { continue; } /* Horde_Icalendar_Vfreebusy only supports timestamps at the * moment. */ $vFb->addBusyPeriod('BUSY', $event->start->timestamp(), null, $event->end->timestamp() - $event->start->timestamp()); } } /* Remove the overlaps. */ $vFb->simplify(); $vCal->addComponent($vFb); /* Return the vFreebusy object if requested. */ if ($returnObj) { return $vFb; } /* Generate the vCal file. */ return $vCal->exportvCalendar(); }