/** * Handles checking for resource availability or cancellation. * * @param Kronolith_Event $event The event whose resources we are saving. * * @return array An array of accepted resource objects. */ public static function checkResources($event) { $accepted_resources = array(); // Don't waste time with resource acceptance if the status is cancelled, // the event will be removed from the resource calendar anyway. if ($event->status != Kronolith::STATUS_CANCELLED) { foreach (array_keys($event->getResources()) as $id) { /* Get the resource and protect against infinite recursion in * case someone is silly enough to add a resource to it's own * event.*/ $resource = Kronolith::getDriver('Resource')->getResource($id); $rcal = $resource->get('calendar'); if ($rcal == $event->calendar) { continue; } Kronolith::getDriver('Resource')->open($rcal); /* Lock the resource and get the response */ if ($resource->get('response_type') == Kronolith_Resource::RESPONSETYPE_AUTO) { $haveLock = $resource->lock(); if (!$haveLock) { throw new Kronolith_Exception(sprintf(_("The resource \"%s\" was locked. Please try again."), $resource->get('name'))); } } else { $haveLock = false; } $response = $resource->getResponse($event); /* Remember accepted resources so we can add the event to their * calendars. Otherwise, clear the lock. */ if ($response == Kronolith::RESPONSE_ACCEPTED) { $accepted_resources[] = $resource; } elseif ($haveLock) { $resource->unlock(); } if ($response == Kronolith::RESPONSE_DECLINED && $event->uid) { $r_driver = Kronolith::getDriver('Resource'); $r_event = $r_driver->getByUID($event->uid, array($resource->get('calendar'))); $r_driver->deleteEvent($r_event, true, true); } /* Add the resource to the event */ $event->addResource($resource, $response); } } else { // If event is cancelled, and actually exists, we need to mark it // as cancelled in resource calendar. foreach (array_keys($event->getResources()) as $id) { $resource = Kronolith::getDriver('Resource')->getResource($id); $rcal = $resource->get('calendar'); if ($rcal == $event->calendar) { continue; } try { Kronolith::getDriver('Resource')->open($rcal); $resource->addEvent($this); } catch (Exception $e) { } } } return $accepted_resources; }
public function html($active = true) { if (!$this->_event) { echo '<h3>' . _("Event not found") . '</h3>'; exit; } if (is_string($this->_event)) { echo '<h3>' . $this->_event . '</h3>'; exit; } global $conf, $prefs; $this->_event->loadHistory(); $creatorId = $this->_event->creator; $description = $this->_event->description; $location = $this->_event->location; $eventurl = $this->_event->url; $private = $this->_event->isPrivate(); $owner = Kronolith::getUserName($creatorId); $status = Kronolith::statusToString($this->_event->status); $attendees = $this->_event->attendees; $resources = $this->_event->getResources(); if ($datetime = Horde_Util::getFormData('datetime')) { $datetime = new Horde_Date($datetime); $month = $datetime->month; $year = $datetime->year; } else { $month = (int) Horde_Util::getFormData('month', date('n')); $year = (int) Horde_Util::getFormData('year', date('Y')); } $dateFormat = $prefs->getValue('date_format'); $timeFormat = $prefs->getValue('twentyFour') ? 'G:i' : 'g:ia'; // Tags $tags = implode(', ', $this->_event->tags); echo '<div id="Event"' . ($active ? '' : ' style="display:none"') . '>'; require KRONOLITH_TEMPLATES . '/view/view.inc'; echo '</div>'; if ($active && $GLOBALS['browser']->hasFeature('dom')) { /* We check for read permissions, because we can always save a * copy if we can read the event. */ if ($this->_event->hasPermission(Horde_Perms::READ) && Kronolith::getDefaultCalendar(Horde_Perms::EDIT)) { $edit = new Kronolith_View_EditEvent($this->_event); $edit->html(false); } if ($this->_event->hasPermission(Horde_Perms::DELETE)) { $delete = new Kronolith_View_DeleteEvent($this->_event); $delete->html(false); } } }
/** * @param array $params * * @return Horde_Url */ public function getViewUrl($params = array(), $full = false, $encoded = true) { if ($this->url) { return new Horde_Url($this->url, !$encoded); } return parent::getViewUrl($params, $full, $encoded); }
/** * Constructor. * * @param Kronolith_Driver_Kolab $driver The backend driver that this * event is stored in. * @param mixed $eventObject Backend specific event object * that this will represent. */ public function __construct(Kronolith_Driver_Kolab $driver, $eventObject = null) { static $alarm; /* Set default alarm value. */ if (!isset($alarm) && isset($GLOBALS['prefs'])) { $alarm = $GLOBALS['prefs']->getValue('default_alarm'); } $this->alarm = $alarm; parent::__construct($driver, $eventObject); }
/** * Constructor. * * @param Kronolith_Driver $driver The backend driver that this event * is stored in. * @param mixed $eventObject Backend specific event object * that this will represent. */ public function __construct(Kronolith_Driver $driver, $eventObject = null) { /* Set default alarm value. */ if (isset($GLOBALS['prefs'])) { $this->alarm = $GLOBALS['prefs']->getValue('default_alarm'); } parent::__construct($driver, $eventObject); if (!empty($this->calendar) && $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar) !== false) { $this->_backgroundColor = $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->background(); $this->_foregroundColor = $GLOBALS['calendar_manager']->getEntry(Kronolith::ALL_CALENDARS, $this->calendar)->foreground(); } }
public function html($active = true) { if (!$this->_event) { echo '<h3>' . _("Event not found") . '</h3>'; exit; } if (is_string($this->_event)) { echo '<h3>' . $this->_event . '</h3>'; exit; } if ($datetime = Horde_Util::getFormData('datetime')) { $datetime = new Horde_Date($datetime); $month = $datetime->month; $year = $datetime->year; $day = $datetime->mday; } else { $month = Horde_Util::getFormData('month', date('n')); $day = Horde_Util::getFormData('mday', date('j')); $year = Horde_Util::getFormData('year', date('Y')); } $url = Horde_Util::getFormData('url'); echo '<div id="DeleteEvent"' . ($active ? '' : ' style="display:none"') . '>'; if (!$this->_event->recurs()) { require KRONOLITH_TEMPLATES . '/delete/one.inc'; } else { require KRONOLITH_TEMPLATES . '/delete/delete.inc'; } echo '</div>'; if ($active && $GLOBALS['browser']->hasFeature('dom')) { if ($this->_event->hasPermission(Horde_Perms::READ)) { $view = new Kronolith_View_Event($this->_event); $view->html(false); } if ($this->_event->hasPermission(Horde_Perms::READ) && Kronolith::getDefaultCalendar(Horde_Perms::EDIT)) { $edit = new Kronolith_View_EditEvent($this->_event); $edit->html(false); } } }
/** * Creates a new event that represents an exception to a recurring event. * * @param Kronolith_Event $event The original recurring event. * @param Kronolith_Event $copy If present, contains a copy of $event, but * with changes from edited event form. * @param stdClass $attributes The attributes passed from the client. * Expected to contain rstart and rend or * rday that represents the original * starting/ending date of the instance. * * @return Kronolith_Event The event representing the exception */ protected function _copyEvent(Kronolith_Event $event, Kronolith_Event $copy = null, $attributes = null) { if (empty($copy)) { $copy = clone $event; } if ($attributes->rstart) { $rstart = new Horde_Date($attributes->rstart); $rstart->setTimezone($event->start->timezone); $rend = new Horde_Date($attributes->rend); $rend->setTimezone($event->end->timezone); } else { $rstart = new Horde_Date($attributes->rday); $rstart->setTimezone($event->start->timezone); $rstart->hour = $event->start->hour; $rstart->min = $event->start->min; $rend = $rstart->add($event->getDuration); $rend->setTimezone($event->end->timezone); $rend->hour = $event->end->hour; $rend->min = $event->end->min; } $uid = $event->uid; $otime = $event->start->strftime('%T'); // Create new event for the exception $nevent = $event->getDriver()->getEvent(); $nevent->baseid = $uid; $nevent->exceptionoriginaldate = new Horde_Date($rstart->strftime('%Y-%m-%d') . 'T' . $otime); $nevent->exceptionoriginaldate->setTimezone($event->start->timezone); $nevent->creator = $event->creator; $nevent->title = $copy->title; $nevent->description = $copy->description; $nevent->location = $copy->location; $nevent->private = $copy->private; $nevent->url = $copy->url; $nevent->status = $copy->status; $nevent->attendees = $copy->attendees; $nevent->setResources($copy->getResources()); $nevent->start = $rstart; $nevent->end = $rend; $nevent->initialized = true; return $nevent; }
/** * Saves an event in the backend. * * If it is a new event, it is added, otherwise the event is updated. * * @param Kronolith_Event $event The event to save. * * @return string The event id. * @throws Horde_Mime_Exception * @throws Kronolith_Exception */ public function saveEvent(Kronolith_Event $event) { if ($event->stored || $event->exists()) { // If this event recurs and has bound exceptions, we must make sure // that the exceptionoriginaldate is updated in those exceptions as // well. See Bug: 13512 if ($event->recurs()) { foreach ($event->boundExceptions() as $bound) { $t = $event->start->strftime('%T'); $bound->exceptionoriginaldate = new Horde_Date($bound->start->strftime('%Y-%m-%d') . 'T' . $t); $bound->save(); } } return $this->_updateEvent($event); } return $this->_addEvent($event); }
/** * Adds an event to the backend. * * @param Kronolith_Event $event The event to save. * * @return string The event id. * @throws Horde_Mime_Exception * @throws Kronolith_Exception */ protected function _addEvent(Kronolith_Event $event) { if (!$event->id) { $event->id = (string) new Horde_Support_Randomid(); } if (!$event->uid) { $event->uid = (string) new Horde_Support_Guid(); } $query = 'INSERT INTO kronolith_events'; $cols_name = ' (event_id, event_uid,'; $cols_values = ' VALUES (?, ?,'; $values = array($event->id, $event->uid); foreach ($event->toProperties() as $key => $val) { $cols_name .= " {$key},"; $cols_values .= ' ?,'; $values[] = $val; } $cols_name .= ' calendar_id)'; $cols_values .= ' ?)'; $values[] = $this->calendar; $query .= $cols_name . $cols_values; try { $this->_db->insert($query, $values); } catch (Horde_Db_Exception $e) { throw new Kronolith_Exception($e); } /* Log the creation of this item in the history log. */ try { $GLOBALS['injector']->getInstance('Horde_History')->log('kronolith:' . $this->calendar . ':' . $event->uid, array('action' => 'add'), true); } catch (Exception $e) { Horde::log($e, 'ERR'); } $this->_addTags($event); /* Update Geolocation */ if ($event->geoLocation) { try { $GLOBALS['injector']->getInstance('Kronolith_Geo')->setLocation($event->id, $event->geoLocation); } catch (Kronolith_Exception $e) { } } /* Notify users about the new event. */ $this->_handleNotifications($event, 'add'); return $event->id; }
/** * Saves an event in the backend. * * If it is a new event, it is added, otherwise the event is updated. * * @param Kronolith_Event $event The event to save. * * @return string The event id. * @throws Horde_Mime_Exception * @throws Kronolith_Exception */ public function saveEvent(Kronolith_Event $event) { if (empty($event->start) || $event->start->year <= 0 || empty($event->end) || $event->end->year <= 0) { throw new Kronolith_Exception(_("Invalid date")); } if ($event->stored || $event->exists()) { return $this->_updateEvent($event); } return $this->_addEvent($event); }
public function html($active = true) { if (!$this->_event) { echo '<h3>' . _("Event not found") . '</h3>'; exit; } if (is_string($this->_event)) { echo '<h3>' . $this->_event . '</h3>'; exit; } $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create(); if ($this->_event->hasPermission(Horde_Perms::EDIT)) { $calendar_id = $this->_event->calendarType . '_' . $this->_event->calendar; } else { $calendar_id = 'internal_' . Kronolith::getDefaultCalendar(Horde_Perms::EDIT); } if (!$this->_event->hasPermission(Horde_Perms::EDIT)) { try { $calendar_id .= '\\' . $this->_event->getShare()->get('owner'); } catch (Exception $e) { } } $GLOBALS['session']->set('kronolith', 'attendees', $this->_event->attendees); $GLOBALS['session']->set('kronolith', 'resources', $this->_event->getResources()); if ($datetime = Horde_Util::getFormData('datetime')) { $datetime = new Horde_Date($datetime); $month = $datetime->month; $year = $datetime->year; } else { $month = Horde_Util::getFormData('month', date('n')); $year = Horde_Util::getFormData('year', date('Y')); } $url = Horde_Util::getFormData('url'); $perms = Horde_Perms::EDIT; if ($this->_event->creator == $GLOBALS['registry']->getAuth()) { $perms |= Kronolith::PERMS_DELEGATE; } $calendars = Kronolith::listCalendars($perms, true); $buttons = array(); if (!$this->_event->hasPermission(Horde_Perms::EDIT) && ($GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('max_events') === true || $GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('max_events') > Kronolith::countEvents())) { $buttons[] = '<input type="submit" class="horde-create" name="saveAsNew" value="' . _("Save As New") . '" />'; } else { if ($this->_event->hasPermission(Horde_Perms::EDIT)) { $buttons[] = '<input type="submit" class="horde-default" name="save" value="' . _("Save Event") . '" />'; } if ($this->_event->initialized) { if (!$this->_event->recurs() && ($GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('max_events') === true || $GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('max_events') > Kronolith::countEvents())) { $buttons[] = '<input type="submit" class="horde-create" name="saveAsNew" value="' . _("Save As New") . '" />'; } } } if (isset($url)) { $cancelurl = new Horde_Url($url); } else { $cancelurl = Horde::url('month.php', true)->add(array('month' => $month, 'year' => $year)); } $event =& $this->_event; $tags = implode(',', array_values($event->tags)); Horde_Core_Ui_JsCalendar::init(array('full_weekdays' => true)); global $page_output; $page_output->addScriptFile('hordecore.js', 'horde'); $page_output->addScriptFile('edit.js'); $page_output->addScriptFile('popup.js', 'horde'); echo '<div id="EditEvent"' . ($active ? '' : ' style="display:none"') . '>'; require KRONOLITH_TEMPLATES . '/edit/edit.inc'; echo '</div>'; if ($active && $GLOBALS['browser']->hasFeature('dom')) { if ($this->_event->hasPermission(Horde_Perms::READ)) { $view = new Kronolith_View_Event($this->_event); $view->html(false); } if ($this->_event->hasPermission(Horde_Perms::DELETE)) { $delete = new Kronolith_View_DeleteEvent($this->_event); $delete->html(false); } } }
/** * Saves an event in the backend. * * @param Kronolith_Event $event The event to save. * * @return string The event id. * @throws Horde_Mime_Exception */ protected function _saveEvent($event, $edit) { $this->synchronize(); $action = $edit ? array('action' => 'modify') : array('action' => 'add'); if (!$event->uid) { $event->uid = $this->_data->generateUID(); $event->id = Horde_Url::uriB64Encode($event->uid); } $object = $event->toKolab(); if ($edit) { $this->_data->modify($object); } else { $this->_data->create($object); } /* Deal with tags */ if ($edit) { $this->_updateTags($event); } else { $this->_addTags($event); } /* Notify about the changed event. */ Kronolith::sendNotification($event, $edit ? 'edit' : 'add'); /* Log the creation/modification of this item in the history log. */ try { $GLOBALS['injector']->getInstance('Horde_History')->log('kronolith:' . $event->calendar . ':' . $event->uid, $action, true); } catch (Exception $e) { Horde::log($e, 'ERR'); } // refresh IMAP cache $this->synchronize(true); if (is_callable('Kolab', 'triggerFreeBusyUpdate')) { //Kolab::triggerFreeBusyUpdate($this->_data->parseFolder($event->calendar)); } return $event->id; }
/** * Updates an existing event in the backend. * * @param Kronolith_Event_Horde $event The event to save. * * @return string The event id. * @throws Kronolith_Exception */ protected function _updateEvent(Kronolith_Event $event) { if (!isset($this->api)) { list($this->api, ) = explode('/', $this->calendar, 2); } try { $this->_params['registry']->call($this->api . '/saveTimeObject', array($event->toTimeobject())); } catch (Horde_Exception $e) { throw new Kronolith_Exception($e); } return $event->timeobject['id']; }
/** * Responsible for any logic needed before the event is saved. Called for * EVERY component in the iCalendar object. Returning false from this method * will cause the current component to be ignored. Returning true causes it * to be processed. * * @param Horde_Icalendar $component The iCalendar component. * * @return boolean True to continue processing, false to ignore. */ protected function _preSave($component) { // Short circuit if we know we don't pass the parent test. if (!parent::_preSave($component)) { return false; } // Ensure we start with a fresh state. $this->_existingEvent = null; $this->_oldAttendees = new Kronolith_Attendee_List(); $this->_noItips = array(); // Get the internal id of the existing copy of the event, if it exists. try { $existing_id = $this->_dav->getInternalObjectId($this->_params['object'], $this->_calendar) ?: preg_replace('/\\.ics$/', '', $this->_params['object']); } catch (Horde_Dav_Exception $e) { $existing_id = $this->_params['object']; } // Check that we don't have newer information already on the server. try { // Exception event, so we can't compare timestamps using ids. // Instead look for baseid/recurrence-id. $rid = $component->getAttribute('RECURRENCE-ID'); $uid = $component->getAttribute('UID'); if (!empty($rid) && !empty($uid)) { $search = new stdClass(); $search->baseid = $uid; $search->recurrenceid = $rid; $results = $this->_driver->search($search); foreach ($results as $days) { foreach ($days as $exception) { // Should only be one... $modified = $exception->modified ?: $exception->created; } } } } catch (Horde_Icalendar_Exception $e) { // Base event or event with no recurrence. try { $this->_existingEvent = $this->_driver->getEvent($existing_id); $this->_existingEvent->loadHistory(); $modified = $this->_existingEvent->modified ?: $this->_existingEvent->created; // Get list of existing attendees. $this->_oldAttendees = $this->_existingEvent->attendees; } catch (Horde_Exception_NotFound $e) { $this->_existingEvent = null; } } try { if (!empty($modified) && $component->getAttribute('LAST-MODIFIED') < $modified->timestamp()) { /* LAST-MODIFIED timestamp of existing entry is newer: * don't replace it. */ return false; } } catch (Horde_Icalendar_Exception $e) { } try { $organizer = $component->getAttribute('ORGANIZER'); $organizer_params = $component->getAttribute('ORGANIZER', true); if (!empty($organizer_params[0]['SCHEDULE-AGENT']) && ($organizer_params[0]['SCHEDULE-AGENT'] == 'CLIENT' || $organizer_params[0]['SCHEDULE-AGENT'] == 'NONE')) { $tmp = str_replace(array('MAILTO:', 'mailto:'), '', $organizer); $tmp = new Horde_Mail_Rfc822_Address($tmp); $this->_noItips[] = $tmp->bare_address; } } catch (Horde_Icalendar_Exception $e) { } try { $attendee = $component->getAttribute('ATTENDEE'); $params = $component->getAttribute('ATTENDEE', true); for ($i = 0; $i < count($attendee); ++$i) { if (!empty($params[$i]['SCHEDULE-AGENT']) && ($params[$i]['SCHEDULE-AGENT'] == 'CLIENT' || $params[$i]['SCHEDULE-AGENT'] == 'NONE')) { $tmp = str_replace(array('MAILTO:', 'mailto:'), '', $attendee[$i]); $tmp = new Horde_Mail_Rfc822_Address($tmp); $this->_noItips[] = $tmp->bare_address; } } } catch (Horde_Icalendar_Exception $e) { } return true; }
/** * Returns a simple object suitable for json transport representing this * event. * * @param boolean $allDay If not null, overrides whether the event is * an all-day event. * @param boolean $full Whether to return all event details. * @param string $time_format The date() format to use for time formatting. * * @return object A simple object. */ public function toJson($allDay = null, $full = false, $time_format = 'H:i') { $json = parent::toJson($allDay, $full, $time_format); if ($this->_ajaxLink) { $json->aj = $this->_ajaxLink; } elseif ($link = (string) $this->getViewUrl(array(), true, false)) { $json->ln = $link; } if (isset($this->_variableLength)) { $json->vl = $this->_variableLength; } return $json; }
/** * Returns a simple object suitable for json transport representing this * event. * * @param array $options An array of options: * * - all_day: (boolean) If not null, overrides whether the event is an * all-day event. * DEFAULT: null (Do not override). * - full: (boolean) Whether to return all event details. * DEFAULT: false (Do not return all details). * - time_format: (string) The date() format to use for time formatting. * DEFAULT: 'H:i' * - history: (boolean) If true, ensures that this event's history is * loaded from the History backend. * DEFAULT: false (Do not ensure history is loaded). * * @return stdClass A simple object. */ public function toJson(array $options = array()) { $options = array_merge(array('all_day' => null, 'full' => false, 'time_format' => 'H:i', 'history' => false), $options); $json = parent::toJson($options); if ($this->_ajaxLink) { $json->aj = $this->_ajaxLink; } elseif ($link = (string) $this->getViewUrl(array(), true, false)) { $json->ln = $link; } if (isset($this->_variableLength)) { $json->vl = $this->_variableLength; } return $json; }
/** * @param string $tabname * @param Kronolith_Event $event */ public static function eventTabs($tabname, $event) { if (!$event->initialized) { return; } $GLOBALS['page_output']->addScriptFile('views.js'); $tabs = new Horde_Core_Ui_Tabs('event', Horde_Variables::getDefaultVariables()); $date = self::currentDate(); $tabs->preserve('datetime', $date->dateString()); $tabs->addTab(htmlspecialchars($event->getTitle()), $event->getViewUrl(), array('tabname' => 'Event', 'id' => 'tabEvent', 'onclick' => 'return ShowTab(\'Event\');')); /* We check for read permissions, because we can always save a copy if * we can read the event. */ if ((!$event->private || $event->creator == $GLOBALS['registry']->getAuth()) && $event->hasPermission(Horde_Perms::READ) && self::getDefaultCalendar(Horde_Perms::EDIT)) { $tabs->addTab($event->hasPermission(Horde_Perms::EDIT) ? _("_Edit") : _("Save As New"), $event->getEditUrl(), array('tabname' => 'EditEvent', 'id' => 'tabEditEvent', 'onclick' => 'return ShowTab(\'EditEvent\');')); } if ($event->hasPermission(Horde_Perms::DELETE)) { $tabs->addTab(_("De_lete"), $event->getDeleteUrl(array('confirm' => 1)), array('tabname' => 'DeleteEvent', 'id' => 'tabDeleteEvent', 'onclick' => 'return ShowTab(\'DeleteEvent\');')); } $tabs->addTab(_("Export"), $event->getExportUrl(), array('tabname' => 'ExportEvent', 'id' => 'tabExportEvent')); echo $tabs->render($tabname); }
/** * Updates an existing event in the backend. * * @param Kronolith_Event $event The event to save. * * @return string The event id. * @throws Horde_Mime_Exception * @throws Kronolith_Exception */ protected function _saveEvent($event) { $ical = new Horde_Icalendar(); $ical->addComponent($event->toiCalendar($ical)); $url = trim($this->_getUrl(), '/') . '/' . $event->id; try { return $this->_getClient($url)->request('PUT', '', $ical->exportvCalendar(), array('Content-Type' => 'text/calendar')); } catch (Horde_Dav_Exception $e) { Horde::log($e, 'INFO'); throw new Kronolith_Exception($e); } }
/** * Handles updating/saving this event's resources. Unless this event recurs, * this will delete this event from any resource calendars that are no * longer needed (as when a resource is removed from an existing event). If * this event is an exception, i.e., contains a baseid, AND $existing is * provided, the resources from the original event are used for purposes * of determining any resources that need to be removed. * * * @param Kronolith_Event|null $existing An existing base event. * @since 4.2.6 */ protected function _handleResources(Kronolith_Event $existing = null) { global $session; if (Horde_Util::getFormData('isajax', false)) { $resources = array(); } else { $resources = $session->get('kronolith', 'resources', Horde_Session::TYPE_ARRAY); } $existingResources = $this->_resources; $newresources = Horde_Util::getFormData('resources'); if (!empty($newresources)) { foreach (explode(',', $newresources) as $id) { try { $resource = Kronolith::getDriver('Resource')->getResource($id); } catch (Kronolith_Exception $e) { $GLOBALS['notification']->push($e->getMessage(), 'horde.error'); continue; } if (!$resource instanceof Kronolith_Resource_Group || $resource->isFree($this)) { $resources[$resource->getId()] = array('attendance' => Kronolith::PART_REQUIRED, 'response' => Kronolith::RESPONSE_NONE, 'name' => $resource->get('name')); } else { $GLOBALS['notification']->push(_("No resources from this group were available"), 'horde.error'); } } } $this->_resources = $resources; // Have the base event, and this is an exception so we must // match the recurrence in the resource's copy of the base event. if (!empty($existing) && $existing->recurs() && !$this->recurs()) { foreach ($existing->getResources() as $rid => $data) { $resource = Kronolith::getDriver('Resource')->getResource($key); $r_event = Kronolith::getDriver('Resource')->getByUID($existing->uid, $resource->calendar); $r_event->recurrence = $event->recurrence; $r_event->save(); } } // If we don't recur, check for removal of any resources so we can // update those resources' calendars. if (!$this->recurs()) { $merged = $existingResources + $this->_resources; $delete = array_diff(array_keys($existingResources), array_keys($this->_resources)); foreach ($delete as $key) { // Resource might be declined, in which case it won't have the event // on it's calendar. if ($merged[$key]['response'] != Kronolith::RESPONSE_DECLINED) { try { Kronolith::getDriver('Resource')->getResource($key)->removeEvent($this); } catch (Kronolith_Exception $e) { $GLOBALS['notification']->push('foo', 'horde.error'); } } } } }