Example #1
0
 /**
  * Constructor
  */
 public function __construct($start, $end)
 {
     if (!$start instanceof qCal_DateTime) {
         $start = qCal_DateTime::factory($start);
     }
     if (!$end instanceof qCal_DateTime) {
         $end = qCal_DateTime::factory($end);
     }
     $this->start = $start;
     $this->end = $end;
     if ($this->getSeconds() < 0) {
         throw new qCal_DateTime_Exception_InvalidPeriod("The start date must come before the end date.");
     }
 }
Example #2
0
 /**
  * Cast a string value into a qCal_DateTime_Period object
  */
 protected function doCast($value)
 {
     $parts = explode("/", $value);
     if (count($parts) !== 2) {
         throw new qCal_DateTime_Exception_InvalidPeriod("A period must contain a start date and either an end date, or a duration of time.");
     }
     $start = qCal_DateTime::factory($parts[0]);
     try {
         $end = qCal_DateTime::factory($parts[1]);
     } catch (qCal_DateTime_Exception $e) {
         // @todo This should probably be a more specific exception
         // invalid date, so try duration
         // @todo: I might want to create a qCal_Date object to represent a duration (not tied to any points in time)
         // using a qCal_Value object here is sort of inconsistent. Plus, I can see value in having that functionality
         // within the qCal_Date subcomponent
         // also, there is a difference in a period and a duration in that if you say start on feb 26 and end on march 2
         // that will be a different "duration" depending on the year. that goes for months with alternate amounts of days too
         $duration = new qCal_DateTime_Duration($parts[1]);
         $end = qCal_DateTime::factory($start->getUnixTimestamp() + $duration->getSeconds());
         // @todo This needs to be updated once qCal_DateTime accepts timestamps
     }
     return new qCal_DateTime_Period($start, $end);
 }
Example #3
0
 /**
  * Fetches instances of the recurrence rule in the given time period. Because recurrences
  * could potentially go on forever, there is no way to fetch ALL instances of a recurrence rule
  * other than providing a date range that spans the entire length of the recurrence.
  * 
  * The way this will need to work is, depending on the frequency, I will find all possible
  * occurrence of the rule. For instance, if this is a "monthly" rule, I'll find out which month
  * to start in, then find all occurrence possible. Then narrow down by the other rules I guess.
  * 
  * @idea Maybe I should build classes for each of the frequency types. That way I could loop over
  * the object and get methods like qCal_DateTime_Recur_Monthly::isNthDay('SU') to find out what sunday
  * of the month it is... stuff like that... I dunno... ?
  * 
  * @throws qCal_DateTime_Exception_InvalidRecur
  * @todo The giant switch in this method is a glaring code smell, but it works for now. I will refactor
  * after version 0.1 and remove the switch (probably will implement qCal_DateTime_Recur_Yearly, qCal_DateTime_Recur_Monthly, etc.)
  */
 public function getRecurrences($start, $end)
 {
     $start = qCal_DateTime::factory($start);
     $end = qCal_DateTime::factory($end);
     if ($start->getUnixTimestamp() > $end->getUnixTimestamp()) {
         throw new qCal_DateTime_Exception_InvalidRecur('Start date must come before end date');
     }
     if (!$this->interval) {
         throw new qCal_DateTime_Exception_InvalidRecur('You must specify an interval');
     }
     $rules = array('bymonth' => array(), 'byweekno' => array(), 'byyearday' => array(), 'byday' => array());
     // byMonth rules
     if (is_array($this->bymonth)) {
         foreach ($this->bymonth as $bymonth) {
             $rules['bymonth'][] = new qCal_DateTime_Recur_Rule_ByMonth($bymonth);
         }
     }
     // byWeekNo rules
     if (is_array($this->byweekno)) {
         foreach ($this->byweekno as $byweekno) {
             $rules['byweekno'][] = new qCal_DateTime_Recur_Rule_ByWeekNo($byweekno);
         }
     }
     // byYearDay rules
     if (is_array($this->byyearday)) {
         foreach ($this->byyearday as $byyearday) {
             $rules['byyearday'][] = new qCal_DateTime_Recur_Rule_ByYearDay($byyearday);
         }
     }
     // byMonthDay rules (these get applied to bymonth rules)
     if (is_array($this->bymonthday)) {
         foreach ($this->bymonthday as $bymonthday) {
             $bmdrule = new qCal_DateTime_Recur_Rule_ByMonthDay($bymonthday);
             foreach ($rules['bymonth'] as $bymonth) {
                 $bymonth->attach($bmdrule);
             }
         }
     }
     // byDay rules (these get applied to bymonth rules if they exist, otherwise simply to year)
     if (is_array($this->byday)) {
         foreach ($this->byday as $byday) {
             $bdrule = new qCal_DateTime_Recur_Rule_ByDay($byday);
             if (is_array($rules['bymonth']) && !empty($rules['bymonth'])) {
                 foreach ($rules['bymonth'] as $bymonth) {
                     $bymonth->attach($bdrule);
                 }
             } else {
                 $rules['byday'][] = $bdrule;
             }
         }
     }
     // byHour rules (these get applied to each rule above)
     if (is_array($this->byhour)) {
         foreach ($this->byhour as $byhour) {
             $bhrule = new qCal_DateTime_Recur_Rule_ByHour($byhour);
             foreach ($rules as $type => $ruleset) {
                 foreach ($ruleset as $rule) {
                     $rule->attach($bhrule);
                 }
             }
         }
     }
     // byMinute rules (these get applied to each rule above)
     if (is_array($this->byminute)) {
         foreach ($this->byminute as $byminute) {
             $bmrule = new qCal_DateTime_Recur_Rule_ByMinute($byminute);
             foreach ($rules as $type => $ruleset) {
                 foreach ($ruleset as $rule) {
                     $rule->attach($bmrule);
                 }
             }
         }
     }
     // bySecond rules (these get applied to each rule above)
     if (is_array($this->bysecond)) {
         foreach ($this->bysecond as $bysecond) {
             $bsrule = new qCal_DateTime_Recur_Rule_BySecond($bysecond);
             foreach ($rules as $type => $ruleset) {
                 foreach ($ruleset as $rule) {
                     $rule->attach($bsrule);
                 }
             }
         }
     }
     return $this->doGetRecurrences($rules, $start, $end);
 }
 /**
  * Timezones should be accessible individually by getTimezone()
  */
 public function testGetTimezone()
 {
     $cal = new qCal_Component_Vcalendar();
     $useastern = new qCal_Component_Vtimezone(array('tzid' => 'US-Eastern'));
     // fake us eastern timezone
     $useastern->attach(new qCal_Component_Standard(array('dtstart' => qCal_DateTime::factory('20090913T000000Z'), 'offsetto' => new qCal_Property_Tzoffsetto('0200'), 'offsetfrom' => new qCal_Property_Tzoffsetfrom('0400'))));
     $uswestern = new qCal_Component_Vtimezone(array('tzid' => 'US-Western'));
     // fake us western timezone
     $uswestern->attach(new qCal_Component_Standard(array('dtstart' => qCal_DateTime::factory('20090913T000000Z'), 'offsetto' => new qCal_Property_Tzoffsetto('0100'), 'offsetfrom' => new qCal_Property_Tzoffsetfrom('0300'))));
     $cal->attach($useastern);
     $cal->attach($uswestern);
     $this->assertIdentical($cal->getTimezone('us-eastern'), $useastern);
 }
 /**
  * Test conversion to UTC
  * @todo The entire process for UTC conversion is hacky at best. Fix it up in the next release.
  */
 public function testUTCConversion()
 {
     $datetime = qCal_DateTime::factory("2/22/1988 5:52am", "America/Denver");
     // February 22, 1988 at 5:52am Mountain Standard Time (-7 hours)
     // UTC is GMT time, which means that the result of this should be the time specified plus seven hours
     $this->assertEqual($datetime->getUtc(), "19880222T125200Z");
 }
 /**
  * Test that all of the right characters are escaped when rendered
  * @todo Need to make sure that when parsing the escape characters are removed.
  */
 public function testCharactersAreEscaped()
 {
     $journal = new qCal_Component_Vjournal(array('summary' => 'The most interesting, but non-interesting journal entry ever.', 'description' => 'This is a sentence that ends with a semi-colon, which I\'m not sure needs to be escaped; I will read the RFC a bit and find out what, exactly, needs to escaped. I know commas do though, and this entry has plenty of those.', 'dtstart' => qCal_DateTime::factory('20090809T113500')));
     $this->assertEqual($journal->render(), "BEGIN:VJOURNAL\r\nSUMMARY:The most interesting\\, but non-interesting journal entry ever.\r\nDESCRIPTION:This is a sentence that ends with a semi-colon\\, which I'm not \r\n sure needs to be escaped; I will read the RFC a bit and find out what\\, exa\r\n ctly\\, needs to escaped. I know commas do though\\, and this entry has plent\r\n y of those.\r\nDTSTART:20090809T113500\r\nEND:VJOURNAL\r\n");
 }
 /**
  * Test that date-time data is handled right
  */
 public function testRawDateTime()
 {
     $value = new qCal_Value_DateTime('2009-04-23 6:00');
     $this->assertEqual($value->getValue(), qCal_DateTime::factory('2009-04-23 6:00'));
 }
Example #8
0
 public function eventToIcal($_event)
 {
     if ($_event instanceof Tinebase_Record_RecordSet) {
         foreach ($_event as $event) {
             $this->eventToIcal($event);
         }
         return $this->_vcalendar;
     }
     // NOTE: we deliver events in originators tz
     $_event->setTimezone($_event->originator_tz);
     if (!in_array($_event->originator_tz, $this->_attachedTimezones)) {
         $this->_vcalendar->attach(self::getVtimezone($_event->originator_tz));
         $this->_attachedTimezones[] = $_event->originator_tz;
     }
     if ($_event->is_all_day_event) {
         $dtstart = new qCal_Property_Dtstart($_event->dtstart->format('Ymd'), array('VALUE' => 'DATE'));
         $dtend = new qCal_Property_Dtend($_event->dtend->format('Ymd'), array('VALUE' => 'DATE'));
     } else {
         $dtstart = new qCal_Property_Dtstart(qCal_DateTime::factory($_event->dtstart->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
         $dtend = new qCal_Property_Dtend(qCal_DateTime::factory($_event->dtend->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
     }
     $vevent = new qCal_Component_Vevent(array('uid' => $_event->uid, 'sequence' => $_event->seq, 'summary' => $_event->summary, 'dtstart' => $dtstart, 'dtend' => $dtend));
     foreach (self::$veventMap as $icalProp => $tineField) {
         if (isset($_event[$tineField])) {
             $vevent->addProperty($icalProp, $_event->{$tineField});
         }
     }
     // rrule
     if ($_event->rrule) {
         $vevent->addProperty('rrule', preg_replace('/(UNTIL=)(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/', '$1$2$3$4T$5$6$7Z', $_event->rrule));
         if ($exdateArray = $_event->exdate) {
             // use multiple EXDATE for the moment, as apple ical uses them
             foreach ($_event->exdate as $exdate) {
                 $exdates = new qCal_Property_Exdate(qCal_DateTime::factory($exdate->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
                 $vevent->addProperty($exdates);
             }
             //                $exdates = new qCal_Property_Exdate(qCal_DateTime::factory(array_shift($exdateArray)->format('Ymd\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
             //                foreach($exdateArray as $exdate) {
             //                    $exdates->addValue(qCal_DateTime::factory($exdate->format('Ymd\THis'), $_event->originator_tz));
             //                }
             //
             //                $vevent->addProperty($exdates);
         }
     }
     // recurid
     if ($_event->isRecurException()) {
         $originalDtStart = $_event->getOriginalDtStart();
         $originalDtStart->setTimezone($_event->originator_tz);
         $vevent->addProperty(new qCal_Property_RecurrenceId(qCal_DateTime::factory($originalDtStart->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz)));
     }
     // organizer
     $organizerId = $_event->organizer instanceof Addressbook_Model_Contact ? array($_event->organizer->getId()) : array($_event->organizer);
     $organizer = Addressbook_Controller_Contact::getInstance()->getMultiple($organizerId, TRUE)->getFirstRecord();
     if ($organizer && ($organizerEmail = $organizer->getPreferedEmailAddress())) {
         $vevent->addProperty(new qCal_Property_Organizer("mailto:{$organizerEmail}", array('CN' => $organizer->n_fileas)));
     }
     // attendee
     if ($_event->attendee) {
         Calendar_Model_Attender::resolveAttendee($_event->attendee, FALSE);
         foreach ($_event->attendee as $attender) {
             $attenderEmail = $attender->getEmail();
             if ($attenderEmail) {
                 $vevent->addProperty(new qCal_Property_Attendee("mailto:{$attenderEmail}", array('CN' => $attender->getName(), 'CUTYPE' => self::$cutypeMap[$attender->user_type], 'EMAIL' => $attenderEmail, 'PARTSTAT' => $attender->status, 'ROLE' => "{$attender->role}-PARTICIPANT", 'RSVP' => 'FALSE')));
             }
         }
     }
     // alarms
     if ($_event->alarms) {
         foreach ($_event->alarms as $alarm) {
             $valarm = new qCal_Component_Valarm(array('ACTION' => 'DISPLAY', 'DESCRIPTION' => $_event->summary));
             // qCal only support DURATION ;-(
             $diffSeconds = $_event->dtstart->php52compat_diff($alarm->alarm_time);
             $valarm->addProperty(new qCal_Property_Trigger($diffSeconds));
             //                if (is_numeric($alarm->minutes_before)) {
             //                    $valarm->addProperty(new qCal_Property_Trigger("-PT{$alarm->minutes_before}M"));
             //                } else {
             //                    $valarm->addProperty(new qCal_Property_Trigger(qCal_DateTime::factory($alarm->alarm_time->format('Ymd\THis'), $_event->originator_tz)), array('TZID' => $_event->originator_tz));
             //                }
             $vevent->attach($valarm);
         }
     }
     // @todo status
     $this->_vcalendar->attach($vevent);
     return $this->_vcalendar;
 }
 /**
  * Provided a date/time object, use this recurrence's rules to determine
  * all of the recurrence times for the date and return them in an array.
  * @param qCal_Date The date object to find time recurrences for
  * @return array A list of time recurrences for the specified date/time
  * @access protected
  * @todo I don't really like the way this is done. Definitely a code smell here.
  * Each of the rules should do their own logic. Something like:
  * 	$seconds = $bySecond->getTimeInstances();
  * 	$minutes = $byMinute->getTimeInstances($seconds);
  * 	$hours = $byHour->getTimeInstances($minutes);
  */
 protected function findTimeRecurrences(qCal_Date $date)
 {
     // find all of the bySeconds
     $seconds = array();
     if ($this->hasRule('qCal_DateTime_Recur_Rule_BySecond')) {
         $seconds = $this->getRule('qCal_DateTime_Recur_Rule_BySecond')->getValues();
         sort($seconds);
     } else {
         $seconds = array($this->getStart()->getTime()->getSecond());
     }
     // find all of the byMinutes
     $minutes = array();
     if ($this->hasRule('qCal_DateTime_Recur_Rule_ByMinute')) {
         $minutesRules = $this->getRule('qCal_DateTime_Recur_Rule_ByMinute')->getValues();
         sort($minutesRules);
     } else {
         $minutesRules = array($this->getStart()->getTime()->getMinute());
     }
     foreach ($minutesRules as $minute) {
         $minutes[$minute] = $seconds;
     }
     // find all of the byHours
     $hours = array();
     if ($this->hasRule('qCal_DateTime_Recur_Rule_ByHour')) {
         $hoursRules = $this->getRule('qCal_DateTime_Recur_Rule_ByHour')->getValues();
         sort($hoursRules);
     } else {
         $hoursRules = array($this->getStart()->getTime()->getHour());
     }
     foreach ($hoursRules as $hour) {
         $hours[$hour] = $minutes;
     }
     // create an array to store times
     $times = array();
     foreach ($hours as $hour => $minutes) {
         foreach ($minutes as $minute => $seconds) {
             foreach ($seconds as $second) {
                 try {
                     // try to build a date/time object
                     $datetime = new qCal_DateTime($date->getYear(), $date->getMonth(), $date->getDay(), $hour, $minute, $second);
                     $times[$datetime->format('YmdHis')] = $datetime;
                 } catch (qCal_DateTime_Exception_InvalidTime $e) {
                     // if the date/time object instantiation fails, this exception will be thrown
                     // @todo Recover from this error and report it. Maybe catch the error and pass it to a log or something?
                     // qCal_Log::logException($e, get_class($this));
                     throw $e;
                 }
             }
         }
     }
     return $times;
 }
Example #10
0
 /**
  * This converts to a qCal_Date for internal storage
  */
 protected function doCast($value)
 {
     // @todo This may be the wrong place to do this...
     if ($value instanceof qCal_DateTime) {
         return $value;
     }
     $date = qCal_DateTime::factory($value);
     return $date;
 }
 /**
  * Set the end date/time for the recurrence set. No recurrences will be returned
  * beyond this date/time
  * @param mixed Either a qCal_DateTime object or a string representing one
  * @return $this
  * @access public
  */
 public function setUntil($datetime)
 {
     $this->until = $datetime instanceof qCal_DateTime ? $datetime : qCal_DateTime::factory($datetime);
     return $this;
 }
 public function testGetUtc()
 {
     $datetime = new qCal_DateTime(2009, 10, 31, 10, 30, 0, "America/Los_Angeles");
     $this->assertEqual($datetime->getUtc(), "20091031T183000Z");
     $this->assertEqual($datetime->getUtc(true), "2009-10-31T18:30:00Z");
 }