Author: Jan Schneider (jan@horde.org)
Inheritance: implements ArrayAccess, implements Countable, implements IteratorAggregate, implements Serializable
Exemple #1
0
 public function testParse()
 {
     $attendees = Kronolith_Attendee_List::parse('Jürgen Doe <*****@*****.**>, Jane Doe,Jack Doe <*****@*****.**>,  jenny@example.com', $this->getMockBuilder('Horde_Notification_Handler')->disableOriginalConstructor()->getMock());
     $this->assertInstanceOf('Kronolith_Attendee_List', $attendees);
     $this->assertEquals(4, count($attendees));
     $expectedAttendees = $this->_getAttendees();
     foreach ($expectedAttendees as &$attendee) {
         $attendee->role = Kronolith::PART_REQUIRED;
         $attendee->response = Kronolith::RESPONSE_NONE;
     }
     $attendees = iterator_to_array($attendees);
     unset($expectedAttendees[5], $expectedAttendees[4]);
     $this->assertEquals($expectedAttendees, array_values($attendees));
     $this->assertEquals(array('email:juergen@example.com', 'name:Jane Doe', 'email:jack@example.com', 'email:jenny@example.com'), array_keys($attendees));
 }
Exemple #2
0
 protected function _postSave(Kronolith_Event $event)
 {
     global $registry;
     if (!$this->_dav->getInternalObjectId($this->_params['object'], $this->_calendar)) {
         $this->_dav->addObjectMap($event->id, $this->_params['object'], $this->_calendar);
     }
     // Send iTip messages if necessary.
     $type = Kronolith::ITIP_REQUEST;
     if ($event->organizer && !Kronolith::isUserEmail($event->creator, $event->organizer)) {
         $type = Kronolith::ITIP_REPLY;
     }
     $event_copy = clone $event;
     $event_copy->attendees = $event->attendees->without($this->_noItips);
     $notification = new Horde_Notification_Handler(new Horde_Notification_Storage_Object());
     Kronolith::sendITipNotifications($event_copy, $notification, $type);
     // Send ITIP_CANCEL to any attendee that was removed, but only if this
     // is the ORGANZIER's copy of the event.
     if (empty($event->organizer) || $registry->getAuth() == $event->creator && Kronolith::isUserEmail($event->creator, $event->organizer)) {
         $removed_attendees = new Kronolith_Attendee_List();
         foreach ($this->_oldAttendees as $old_attendee) {
             if (!$event->attendees->has($old_attendee)) {
                 $removed_attendees->add($old_attendee);
             }
         }
         if (count($removed_attendees)) {
             $cancelEvent = clone $event;
             Kronolith::sendITipNotifications($cancelEvent, $notification, Kronolith::ITIP_CANCEL, null, null, $removed_attendees);
         }
     }
 }
Exemple #3
0
 /**
  * Save a new or update an existing event from the AJAX event detail view.
  *
  * Request parameters used:
  * - event:          The event id.
  * - cal:            The calendar id.
  * - targetcalendar: If moving events, the targetcalendar to move to.
  * - as_new:         Save an existing event as a new event.
  * - recur_edit:     If editing an instance of a recurring event series,
  *                   how to apply the edit [current|future|all].
  * - rstart:         If editing an instance of a recurring event series,
  *                   the original start datetime of this instance.
  * - rend:           If editing an instance of a recurring event series,
  *                   the original ending datetime of this instance.
  * - sendupdates:    Should updates be sent to attendees?
  * - cstart:         Start time of the client cache.
  * - cend:           End time of the client cache.
  */
 public function saveEvent()
 {
     global $injector, $notification, $registry;
     $result = $this->_signedResponse($this->vars->targetcalendar);
     if (!($kronolith_driver = $this->_getDriver($this->vars->targetcalendar))) {
         return $result;
     }
     if ($this->vars->as_new) {
         unset($this->vars->event);
     }
     if (!$this->vars->event) {
         $perms = $injector->getInstance('Horde_Core_Perms');
         if ($perms->hasAppPermission('max_events') !== true && $perms->hasAppPermission('max_events') <= Kronolith::countEvents()) {
             Horde::permissionDeniedError('kronolith', 'max_events', sprintf(_("You are not allowed to create more than %d events."), $perms->hasAppPermission('max_events')));
             return $result;
         }
     }
     if ($this->vars->event && $this->vars->cal && $this->vars->cal != $this->vars->targetcalendar) {
         if (strpos($kronolith_driver->calendar, '\\')) {
             list($target, $user) = explode('\\', $kronolith_driver->calendar, 2);
         } else {
             $target = $kronolith_driver->calendar;
             $user = $registry->getAuth();
         }
         $kronolith_driver = $this->_getDriver($this->vars->cal);
         // Only delete the event from the source calendar if this user has
         // permissions to do so.
         try {
             $sourceShare = Kronolith::getInternalCalendar($kronolith_driver->calendar);
             $share = Kronolith::getInternalCalendar($target);
             if ($sourceShare->hasPermission($registry->getAuth(), Horde_Perms::DELETE) && ($user == $registry->getAuth() && $share->hasPermission($registry->getAuth(), Horde_Perms::EDIT) || $user != $registry->getAuth() && $share->hasPermission($registry->getAuth(), Kronolith::PERMS_DELEGATE))) {
                 $kronolith_driver->move($this->vars->event, $target);
                 $kronolith_driver = $this->_getDriver($this->vars->targetcalendar);
             }
         } catch (Exception $e) {
             $notification->push(sprintf(_("There was an error moving the event: %s"), $e->getMessage()), 'horde.error');
             return $result;
         }
     }
     if ($this->vars->as_new) {
         $event = $kronolith_driver->getEvent();
     } else {
         try {
             // Note that when this is a new event, $this->vars->event will
             // be empty, so this will create a new event.
             $event = $kronolith_driver->getEvent($this->vars->event);
         } catch (Horde_Exception_NotFound $e) {
             $notification->push(_("The requested event was not found."), 'horde.error');
             return $result;
         } catch (Exception $e) {
             $notification->push($e);
             return $result;
         }
     }
     if (!$event->hasPermission(Horde_Perms::EDIT)) {
         $notification->push(_("You do not have permission to edit this event."), 'horde.warning');
         return $result;
     }
     $removed_attendees = new Kronolith_Attendee_List();
     $old_attendees = new Kronolith_Attendee_List();
     if ($this->vars->recur_edit && $this->vars->recur_edit != 'all') {
         switch ($this->vars->recur_edit) {
             case 'current':
                 $attributes = new stdClass();
                 $attributes->rstart = $this->vars->rstart;
                 $attributes->rend = $this->vars->rend;
                 $this->_addException($event, $attributes);
                 // Create a copy of the original event so we can read in the
                 // new form values for the exception. We also MUST reset the
                 // recurrence property even though we won't be using it, since
                 // clone() does not do a deep copy. Otherwise, the original
                 // event's recurrence will become corrupt.
                 $newEvent = clone $event;
                 $newEvent->recurrence = new Horde_Date_Recurrence($event->start);
                 $newEvent->readForm($event);
                 // Create an exception event from the new properties.
                 $exception = $this->_copyEvent($event, $newEvent, $attributes);
                 $exception->start = $newEvent->start;
                 $exception->end = $newEvent->end;
                 // Save the new exception.
                 $attributes->cstart = $this->vars->cstart;
                 $attributes->cend = $this->vars->cend;
                 $result = $this->_saveEvent($exception, $event, $attributes);
                 break;
             case 'future':
                 $instance = new Horde_Date($this->vars->rstart, $event->timezone);
                 $exception = clone $instance;
                 $exception->mday--;
                 if ($event->end->compareDate($exception) > 0) {
                     // Same as 'all' since this is the first recurrence.
                     $this->vars->recur_edit = 'all';
                     return $this->saveEvent();
                 } else {
                     $event->recurrence->setRecurEnd($exception);
                     $newEvent = $kronolith_driver->getEvent();
                     $newEvent->readForm();
                     $newEvent->uid = null;
                     $result = $this->_saveEvent($newEvent, $event, $this->vars, true);
                 }
         }
     } else {
         $old_start = !empty($event->start) ? clone $event->start : false;
         $old_end = !empty($event->end) ? clone $event->end : false;
         $old_recurrence = !empty($event->recurrence) ? clone $event->recurrence : false;
         try {
             $old_attendees = $event->attendees;
             $event->readForm();
             foreach ($old_attendees as $old_attendee) {
                 if (!$event->attendees->has($old_attendee)) {
                     $removed_attendees->add($old_attendee);
                 }
             }
             if (!empty($old_start) && !empty($old_end) && $event->recurs() && ($old_start->compareTime($event->start) !== 0 || $old_end->compareTime($event->end) !== 0) || $old_recurrence && !$event->recurrence->isEqual($old_recurrence)) {
                 // Disconnect any existing exceptions when the
                 // start/end time changes still @todo this when the
                 // recurrence series type/properties change too.
                 $event->disconnectExceptions();
             }
             $result = $this->_saveEvent($event);
         } catch (Exception $e) {
             $notification->push($e);
             return $result;
         }
     }
     if ($this->vars->sendupdates) {
         if ($this->vars->attendance) {
             Kronolith::sendITipNotifications($event, $notification, Kronolith::ITIP_REPLY);
         }
         // Only the ORGANIZER's copy should trigger a REQUEST or CANCEL.
         if (empty($event->organizer)) {
             $type = $event->status == Kronolith::STATUS_CANCELLED ? Kronolith::ITIP_CANCEL : Kronolith::ITIP_REQUEST;
             Kronolith::sendITipNotifications($event, $notification, $type);
         }
     }
     // Send a CANCEL iTip for attendees that have been removed, but only if
     // the entire event isn't being marked as cancelled (which would be
     // caught above).
     if (empty($event->organizer) && count($removed_attendees)) {
         $cancelEvent = clone $event;
         Kronolith::sendITipNotifications($cancelEvent, $notification, Kronolith::ITIP_CANCEL, null, null, $removed_attendees);
     }
     Kronolith::notifyOfResourceRejection($event);
     return $result;
 }
Exemple #4
0
/**
 * Copyright 2004-2007 Code Fusion  <http://www.codefusion.co.za/>
 * Copyright 2004-2007 Stuart Binge <*****@*****.**>
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.horde.org/licenses/gpl.
 */
require_once __DIR__ . '/lib/Application.php';
Horde_Registry::appInit('kronolith');
if (Kronolith::showAjaxView()) {
    Horde::url('', true)->redirect();
}
// Get the current attendees array from the session cache.
$attendees = $session->get('kronolith', 'attendees');
if (!$attendees) {
    $attendees = new Kronolith_Attendee_List();
}
$resources = $session->get('kronolith', 'resources', Horde_Session::TYPE_ARRAY);
$editAttendee = null;
// Get the current Free/Busy view; default to the 'day' view if none specified.
$view = Horde_Util::getFormData('view', 'Day');
// Get the date information.
$start = new Horde_Date(Horde_Util::getFormData('startdate'), date_default_timezone_get());
switch ($view) {
    case 'Day':
        $end = clone $start;
        $end->mday++;
        break;
    case 'Workweek':
    case 'Week':
        $diff = $start->dayOfWeek() - ($view == 'Workweek' ? 1 : $prefs->getValue('week_start_monday'));
Exemple #5
0
 /**
  * Reads form/post data and updates this event's properties.
  *
  * @param  Kronolith_Event|null $existing  If this is an exception event
  *                                         this is taken as the base event.
  *                                         @since 4.2.6
  *
  */
 public function readForm(Kronolith_Event $existing = null)
 {
     global $notification, $prefs, $registry, $session;
     // Event owner.
     $targetcalendar = Horde_Util::getFormData('targetcalendar');
     if (strpos($targetcalendar, '\\')) {
         list(, $this->creator) = explode('\\', $targetcalendar, 2);
     } elseif (!isset($this->_id)) {
         $this->creator = $registry->getAuth();
     }
     // Basic fields.
     $this->title = Horde_Util::getFormData('title', $this->title);
     $this->description = Horde_Util::getFormData('description', $this->description);
     $this->location = Horde_Util::getFormData('location', $this->location);
     $this->timezone = Horde_Util::getFormData('timezone', $this->timezone);
     $this->private = (bool) Horde_Util::getFormData('private');
     // if the field is empty you are the organizer (and so organizer should be null)
     $this->organizer = Horde_Util::getFormData('organizer', $this->organizer) ?: null;
     // URL.
     $url = Horde_Util::getFormData('eventurl', $this->url);
     if (strlen($url)) {
         // Analyze and re-construct.
         $url = @parse_url($url);
         if ($url) {
             if (function_exists('http_build_url')) {
                 if (empty($url['path'])) {
                     $url['path'] = '/';
                 }
                 $url = http_build_url($url);
             } else {
                 $new_url = '';
                 if (isset($url['scheme'])) {
                     $new_url .= $url['scheme'] . '://';
                 }
                 if (isset($url['user'])) {
                     $new_url .= $url['user'];
                     if (isset($url['pass'])) {
                         $new_url .= ':' . $url['pass'];
                     }
                     $new_url .= '@';
                 }
                 if (isset($url['host'])) {
                     // Convert IDN hosts to ASCII.
                     if (function_exists('idn_to_ascii')) {
                         $url['host'] = @idn_to_ascii($url['host']);
                     } elseif (Horde_Mime::is8bit($url['host'])) {
                         //throw new Kronolith_Exception(_("Invalid character in URL."));
                         $url['host'] = '';
                     }
                     $new_url .= $url['host'];
                 }
                 if (isset($url['path'])) {
                     $new_url .= $url['path'];
                 }
                 if (isset($url['query'])) {
                     $new_url .= '?' . $url['query'];
                 }
                 if (isset($url['fragment'])) {
                     $new_url .= '#' . $url['fragment'];
                 }
                 $url = $new_url;
             }
         }
     }
     $this->url = $url;
     // Status.
     $this->status = Horde_Util::getFormData('status', $this->status);
     // Attendees.
     $attendees = $session->get('kronolith', 'attendees');
     if (!$attendees) {
         $attendees = new Kronolith_Attendee_List();
     }
     $newattendees = Horde_Util::getFormData('attendees');
     $userattendees = Horde_Util::getFormData('users');
     if (!is_null($newattendees) || !is_null($userattendees)) {
         if ($newattendees) {
             $newattendees = Kronolith_Attendee_List::parse(trim($newattendees), $notification);
         } else {
             $newattendees = new Kronolith_Attendee_List();
         }
         if ($userattendees) {
             foreach (explode(',', $userattendees) as $user) {
                 if (!($newUser = Kronolith::validateUserAttendee($user))) {
                     $notification->push(sprintf(_("The user \"%s\" does not exist."), $newUser), 'horde.error');
                 } else {
                     $newattendees->add($newUser);
                 }
             }
         }
         // First add new attendees missing in the current list.
         foreach ($newattendees as $attendee) {
             if (!$attendees->has($attendee)) {
                 $attendees->add($attendee);
             }
         }
         // Now check for attendees in the current list that don't exist in
         // the new attendee list anymore.
         $finalAttendees = new Kronolith_Attendee_List();
         foreach ($attendees as $attendee) {
             if (!$newattendees->has($attendee)) {
                 continue;
             }
             if (Kronolith::isUserEmail($this->creator, $attendee->email)) {
                 $attendee->response = Horde_Util::getFormData('attendance');
             }
             $finalAttendees->add($attendee);
         }
         $attendees = $finalAttendees;
     }
     $this->attendees = $attendees;
     // Event start.
     $allDay = Horde_Util::getFormData('whole_day');
     if ($start_date = Horde_Util::getFormData('start_date')) {
         // From ajax interface.
         $this->start = Kronolith::parseDate($start_date . ' ' . Horde_Util::getFormData('start_time'), true, $this->timezone);
         if ($allDay) {
             $this->start->hour = $this->start->min = $this->start->sec = 0;
         }
     } elseif ($start = Horde_Util::getFormData('start')) {
         // From traditional interface.
         $start_year = $start['year'];
         $start_month = $start['month'];
         $start_day = $start['day'];
         $start_hour = Horde_Util::getFormData('start_hour');
         $start_min = Horde_Util::getFormData('start_min');
         $am_pm = Horde_Util::getFormData('am_pm');
         if (!$prefs->getValue('twentyFour')) {
             if ($am_pm == 'PM') {
                 if ($start_hour != 12) {
                     $start_hour += 12;
                 }
             } elseif ($start_hour == 12) {
                 $start_hour = 0;
             }
         }
         if (Horde_Util::getFormData('end_or_dur') == 1) {
             if ($allDay) {
                 $start_hour = 0;
                 $start_min = 0;
                 $dur_day = 0;
                 $dur_hour = 24;
                 $dur_min = 0;
             } else {
                 $dur_day = (int) Horde_Util::getFormData('dur_day');
                 $dur_hour = (int) Horde_Util::getFormData('dur_hour');
                 $dur_min = (int) Horde_Util::getFormData('dur_min');
             }
         }
         $this->start = new Horde_Date(array('hour' => $start_hour, 'min' => $start_min, 'month' => $start_month, 'mday' => $start_day, 'year' => $start_year), $this->timezone);
     }
     // Event end.
     if ($end_date = Horde_Util::getFormData('end_date')) {
         // From ajax interface.
         $this->end = Kronolith::parseDate($end_date . ' ' . Horde_Util::getFormData('end_time'), true, $this->timezone);
         if ($allDay) {
             $this->end->hour = $this->end->min = $this->end->sec = 0;
             $this->end->mday++;
         }
     } elseif (Horde_Util::getFormData('end_or_dur') == 1) {
         // Event duration from traditional interface.
         $this->end = new Horde_Date(array('hour' => $start_hour + $dur_hour, 'min' => $start_min + $dur_min, 'month' => $start_month, 'mday' => $start_day + $dur_day, 'year' => $start_year));
     } elseif ($end = Horde_Util::getFormData('end')) {
         // From traditional interface.
         $end_year = $end['year'];
         $end_month = $end['month'];
         $end_day = $end['day'];
         $end_hour = Horde_Util::getFormData('end_hour');
         $end_min = Horde_Util::getFormData('end_min');
         $end_am_pm = Horde_Util::getFormData('end_am_pm');
         if (!$prefs->getValue('twentyFour')) {
             if ($end_am_pm == 'PM') {
                 if ($end_hour != 12) {
                     $end_hour += 12;
                 }
             } elseif ($end_hour == 12) {
                 $end_hour = 0;
             }
         }
         $this->end = new Horde_Date(array('hour' => $end_hour, 'min' => $end_min, 'month' => $end_month, 'mday' => $end_day, 'year' => $end_year), $this->timezone);
         if ($this->end->compareDateTime($this->start) < 0) {
             $this->end = new Horde_Date($this->start);
         }
     }
     $this->allday = false;
     // Alarm.
     if (!is_null($alarm = Horde_Util::getFormData('alarm'))) {
         if ($alarm) {
             $value = Horde_Util::getFormData('alarm_value');
             $unit = Horde_Util::getFormData('alarm_unit');
             if ($value == 0) {
                 $value = $unit = 1;
             }
             $this->alarm = $value * $unit;
             // Notification.
             if (Horde_Util::getFormData('alarm_change_method')) {
                 $types = Horde_Util::getFormData('event_alarms');
                 $methods = array();
                 if (!empty($types)) {
                     foreach ($types as $type) {
                         $methods[$type] = array();
                         switch ($type) {
                             case 'notify':
                                 $methods[$type]['sound'] = Horde_Util::getFormData('event_alarms_sound');
                                 break;
                             case 'mail':
                                 $methods[$type]['email'] = Horde_Util::getFormData('event_alarms_email');
                                 break;
                             case 'popup':
                                 break;
                         }
                     }
                 }
                 $this->methods = $methods;
             } else {
                 $this->methods = array();
             }
         } else {
             $this->alarm = 0;
             $this->methods = array();
         }
     }
     // Recurrence.
     $this->recurrence = $this->readRecurrenceForm($this->start, $this->timezone, $this->recurrence);
     // Convert to local timezone.
     $this->setTimezone(false);
     $this->_handleResources($existing);
     // Tags.
     $this->tags = Horde_Util::getFormData('tags', $this->tags);
     // Geolocation
     if (Horde_Util::getFormData('lat') && Horde_Util::getFormData('lon')) {
         $this->geoLocation = array('lat' => Horde_Util::getFormData('lat'), 'lon' => Horde_Util::getFormData('lon'), 'zoom' => Horde_Util::getFormData('zoom'));
     }
     $this->initialized = true;
 }