private function applyICalendarTimes($start, $end, $timezoneID = null)
 {
     $utc = new DateTimezone('UTC');
     $timezone = null;
     $userTimeZone = Phprojekt_User_User::getUserDateTimeZone();
     if ('Z' === substr($start, -1)) {
         $timezone = $utc;
     } else {
         if (!is_null($timezoneID)) {
             $timezone = new DateTimeZone($timezoneID);
         } else {
             $timezone = $userTimeZone;
         }
     }
     // We can't use ->setTimezone with the timezones returned by getUserDateTimeZone, as these are non-standard
     // timezones. Unless we start storing correct timezones, we can't directly set the user timezone, so we go to
     // UTC and convert to usertime from there. Because utcToUser returns a unix timestamp, but ActiveRecords expects
     // a "Y-m-d H:i:s" timestamp, we have to go through Datetime again.
     $start = new Datetime($start, $timezone);
     $start->setTimezone($utc);
     $startTs = Phprojekt_Converter_Time::utcToUser($start->format('Y-m-d H:i:s'));
     $start = new Datetime('@' . $startTs);
     $end = new Datetime($end, $timezone);
     $end->setTimezone($utc);
     $endTs = Phprojekt_Converter_Time::utcToUser($end->format('Y-m-d H:i:s'));
     $end = new Datetime('@' . $endTs);
     if ($start->diff($end)->invert) {
         throw new Sabre_DAV_Exception_BadRequest('Start must be before End');
     }
     $this->_timecard->startDatetime = $start->format('Y-m-d H:i:s');
     if ($start->format('z') == $end->format('z')) {
         // Same day
         $this->_timecard->endTime = $end->format('H:i:s');
     } else {
         $this->_timecard->endTime = '23:59:00';
     }
 }
Exemple #2
0
 /**
  * Updates this Calendar2 object with data from the given VEVENT
  *
  * The returned object must be save()d before it is persistent.
  * This also means that additional changes can be made before any database calls are made.
  *
  * @param Sabre_VObject_Component $vevent The vevent component
  *
  * @throws Exception If the provided component is not a vevent
  *
  * @return void
  */
 public function fromVObject(Sabre_VObject_Component $vevent)
 {
     if (strtolower($vevent->name) !== 'vevent') {
         throw new Exception("Invalid type of vobject_component passed to Calendar2_Models_Calendar2::fromVobject ({$vevent->name})");
     }
     // Workarounds for missing features. We currently don't support locale-time (we just assume it's the user's
     // usual timzeone) or date values without time (we just assume 0800 - 2000 there).
     if (!is_null($vevent->dtstart['VALUE']) && $vevent->dtstart['VALUE']->value === 'DATE') {
         // No T means it's only a date. iCalendar dicates that dtend must be a date, too.
         $vevent->dtstart->value .= 'T080000';
         unset($vevent->dtstart['VALUE']);
         // Caldav end dates are not inclusive
         $end = new Datetime($vevent->dtend->value);
         $end->sub(new DateInterval('P1D'));
         $vevent->dtend->value = $end->format('Ymd') . 'T200000';
         unset($vevent->dtend['VALUE']);
     }
     $utc = new DateTimezone('UTC');
     $timezone = null;
     if ('Z' === substr($vevent->dtstart->value, -1)) {
         $timezone = $utc;
     } else {
         if (!is_null($vevent->dtstart['tzid'])) {
             $timezone = new DateTimeZone($vevent->dtstart['tzid']->value);
         } else {
             $timezone = Phprojekt_User_User::getUserDateTimeZone();
         }
     }
     // 0-1
     // handled:
     //  last-mod, description, dtstart, location, summary, uid
     // not handled
     //  class, created, geo, organizer, priority, dtstamp, seq, status, transp, url, recurid
     //
     // none or one of these two
     //  dtend, duration (only assumes dtend case for now)
     //
     // 0 - n
     // TODO: Check how we can handle these. Maybe just concat them?
     // handling: (only one is handled atm, though)
     //  comment, rrule
     // not handling:
     //  attach, attendee, categories, contact, exdate, exrule, rstatus, related, resources, rdate, x-prop
     $mappable = array(array('veventkey' => 'SUMMARY', 'ourkey' => 'summary', 'default' => '_'), array('veventkey' => 'LOCATION', 'ourkey' => 'location', 'default' => ''), array('veventkey' => 'DESCRIPTION', 'ourkey' => 'description', 'default' => ''), array('veventkey' => 'COMMENT', 'ourkey' => 'comments'), array('veventkey' => 'UID', 'ourkey' => 'uid'), array('veventkey' => 'LAST-MODIFIED', 'ourkey' => 'lastModified'), array('veventkey' => 'RRULE', 'ourkey' => 'rrule', 'default' => ''));
     foreach ($mappable as $m) {
         if (isset($vevent->{$m}['veventkey'])) {
             $this->{$m}['ourkey'] = $vevent->{$m}['veventkey'];
         } else {
             if (array_key_exists('default', $m)) {
                 $this->{$m}['ourkey'] = $m['default'];
             }
         }
     }
     $start = new Datetime($vevent->dtstart->value, $timezone);
     $start->setTimezone($utc);
     $this->start = Phprojekt_Converter_Time::utcToUser($start->format('Y-m-d H:i:s'));
     if ($vevent->dtend) {
         $end = new Datetime($vevent->dtend->value, $timezone);
     } else {
         if ($vevent->duration) {
             $duration = new DateInterval($vevent->duration->value);
             $end = clone $start;
             $end->add($duration);
         }
     }
     $end->setTimezone($utc);
     $this->end = Phprojekt_Converter_Time::utcToUser($end->format('Y-m-d H:i:s'));
 }
 /**
  * Return ical busy times for the given time period and user. If no
  * user is given, default to the currently logged in user.
  *
  * Request parameters:
  *  int         user    => The id of the user. May be null.
  *  datetime    start   => The start of the period to check.
  *  datetime    end     => The end of the period to check.
  *
  * Response
  *  Array of {
  *      datetime start => The start of the busy period.
  *      datetime end   => The end of the busy period.
  *  }
  */
 public function jsonBusyTimesAction()
 {
     $user = $this->getRequest()->getParam('user', Phprojekt_Auth_Proxy::getEffectiveUserId());
     $start = $this->getRequest()->getParam('start');
     $end = $this->getRequest()->getParam('end');
     if (!Cleaner::validate('int', $user)) {
         throw new Zend_Controller_Action_Exception("Invalid id '{$id}'", 400);
     }
     $user = (int) $user;
     if (!self::_validateTimestamp($start)) {
         throw new Zend_Controller_Action_Exception("Invalid start timestamp '{$start}'", 400);
     }
     if (!self::_validateTimestamp($end)) {
         throw new Zend_Controller_Action_Exception("Invalid end timestamp '{$start}'", 400);
     }
     $start = new Datetime($start, Phprojekt_User_User::getUserDateTimeZone());
     $end = new Datetime($end, Phprojekt_User_User::getUserDateTimeZone());
     $model = new Calendar2_Models_Calendar2();
     $events = $model->fetchAllForPeriod($start, $end);
     $busyPeriods = array();
     foreach ($events as $event) {
         $busyPeriods[] = array('start' => new Datetime($event->start, new DateTimeZone('UTC')), 'end' => new Datetime($event->end, new DateTimeZone('UTC')));
     }
     Phprojekt_Converter_Json::echoConvert(Calendar2_Helper_Time::compactPeriods($busyPeriods));
 }