public function testIsValid()
 {
     // test invalid by normal validation actions
     $rrule = new Calendar_Model_Rrule(array('interval' => 'NotAnInt'), true);
     $rrule->bypassFilters = false;
     $this->assertFalse($rrule->isValid(false));
     // count and until are not allowed together
     $rrule = new Calendar_Model_Rrule(array('count' => '10', 'until' => '2012-01-09 09:33:00'), true);
     $this->assertFalse($rrule->isValid(false), 'until & count');
     // test invalid by setFromString
     $this->setExpectedException('Tinebase_Exception_Record_Validation');
     $rruleString = "FREQ=WEEKLY;INTERVAL=NotAnInt";
     $rrule = new Calendar_Model_Rrule(array());
     $rrule->setFromString($rruleString);
 }
 /**
  * Computes the Recurrence set of the given event leaving out $_event->exdate and $_exceptions
  * 
  * @todo respect rrule_until!
  *
  * @param  Calendar_Model_Event         $_event
  * @param  Tinebase_Record_RecordSet    $_exceptions
  * @param  Tinebase_DateTime            $_from
  * @param  Tinebase_DateTime            $_until
  * @return Tinebase_Record_RecordSet
  * @throws Tinebase_Exception_UnexpectedValue
  */
 public static function computeRecurrenceSet($_event, $_exceptions, $_from, $_until)
 {
     if (!$_event->dtstart instanceof Tinebase_DateTime) {
         throw new Tinebase_Exception_UnexpectedValue('Event needs DateTime dtstart: ' . print_r($_event->toArray(), TRUE));
     }
     $rrule = new Calendar_Model_Rrule(NULL, TRUE);
     $rrule->setFromString($_event->rrule);
     $exceptionRecurIds = self::getExceptionsRecurIds($_event, $_exceptions);
     $recurSet = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     switch ($rrule->freq) {
         case self::FREQ_DAILY:
             self::_computeRecurDaily($_event, $rrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             break;
         case self::FREQ_WEEKLY:
             // default BYDAY clause
             if (!$rrule->byday) {
                 $rrule->byday = array_search($_event->dtstart->format('w'), self::$WEEKDAY_DIGIT_MAP);
             }
             if (!$rrule->wkst) {
                 $rrule->wkst = self::getWeekStart();
             }
             $weekDays = array_keys(self::$WEEKDAY_DIGIT_MAP);
             array_splice($weekDays, 0, 0, array_splice($weekDays, array_search($rrule->wkst, $weekDays)));
             $dailyrrule = clone $rrule;
             $dailyrrule->freq = self::FREQ_DAILY;
             $dailyrrule->interval = 7 * $rrule->interval;
             $eventLength = $_event->dtstart->diff($_event->dtend);
             foreach (explode(',', $rrule->byday) as $recurWeekDay) {
                 // NOTE: in weekly computation, each wdays base event is a recur instance itself
                 $baseEvent = clone $_event;
                 // NOTE: skipping must be done in organizer_tz
                 $baseEvent->dtstart->setTimezone($_event->originator_tz);
                 $direction = array_search($recurWeekDay, $weekDays) >= array_search(array_search($baseEvent->dtstart->format('w'), self::$WEEKDAY_DIGIT_MAP), $weekDays) ? +1 : -1;
                 self::skipWday($baseEvent->dtstart, $recurWeekDay, $direction, TRUE);
                 $baseEvent->dtstart->setTimezone('UTC');
                 $baseEvent->dtend = clone $baseEvent->dtstart;
                 $baseEvent->dtend->add($eventLength);
                 self::_computeRecurDaily($baseEvent, $dailyrrule, $exceptionRecurIds, $_from, $_until, $recurSet);
                 // check if base event (recur instance) needs to be added to the set
                 if ($baseEvent->dtstart > $_event->dtstart && $baseEvent->dtstart >= $_from && $baseEvent->dtstart < $_until) {
                     if (!in_array($baseEvent->setRecurId($baseEvent->getId()), $exceptionRecurIds)) {
                         self::addRecurrence($baseEvent, $recurSet);
                     }
                 }
             }
             break;
         case self::FREQ_MONTHLY:
             if ($rrule->byday) {
                 self::_computeRecurMonthlyByDay($_event, $rrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             } else {
                 self::_computeRecurMonthlyByMonthDay($_event, $rrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             }
             break;
         case self::FREQ_YEARLY:
             $yearlyrrule = clone $rrule;
             $yearlyrrule->freq = self::FREQ_MONTHLY;
             $yearlyrrule->interval = 12;
             $baseEvent = clone $_event;
             $originatorsDtstart = clone $baseEvent->dtstart;
             $originatorsDtstart->setTimezone($_event->originator_tz);
             // @TODO respect BYMONTH
             if ($rrule->bymonth && $rrule->bymonth != $originatorsDtstart->format('n')) {
                 // adopt
                 $diff = (12 + $rrule->bymonth - $originatorsDtstart->format('n')) % 12;
                 // NOTE: skipping must be done in organizer_tz
                 $baseEvent->dtstart->setTimezone($_event->originator_tz);
                 $baseEvent->dtend->setTimezone($_event->originator_tz);
                 $baseEvent->dtstart->addMonth($diff);
                 $baseEvent->dtend->addMonth($diff);
                 $baseEvent->dtstart->setTimezone('UTC');
                 $baseEvent->dtend->setTimezone('UTC');
                 // check if base event (recur instance) needs to be added to the set
                 if ($baseEvent->dtstart->isLater($_from) && $baseEvent->dtstart->isEarlier($_until)) {
                     if (!in_array($baseEvent->setRecurId($baseEvent->getId()), $exceptionRecurIds)) {
                         self::addRecurrence($baseEvent, $recurSet);
                     }
                 }
             }
             if ($rrule->byday) {
                 self::_computeRecurMonthlyByDay($baseEvent, $yearlyrrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             } else {
                 self::_computeRecurMonthlyByMonthDay($baseEvent, $yearlyrrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             }
             break;
     }
     return $recurSet;
 }
 /**
  * sets rrule until helper field
  *
  * @return void
  */
 public function setRruleUntil()
 {
     if (empty($this->rrule)) {
         $this->rrule_until = NULL;
     } else {
         $rrule = $this->rrule;
         if (!$this->rrule instanceof Calendar_Model_Rrule) {
             $rrule = new Calendar_Model_Rrule(array());
             $rrule->setFromString($this->rrule);
             $this->rrule = $rrule;
         }
         if (isset($rrule->count)) {
             $this->rrule_until = NULL;
             $exdates = $this->exdate;
             $this->exdate = NULL;
             $lastOccurrence = Calendar_Model_Rrule::computeNextOccurrence($this, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $this->dtend, $rrule->count - 1);
             $this->rrule_until = $lastOccurrence->dtend;
             $this->exdate = $exdates;
         } else {
             // set until to end of day in organizers timezone.
             // NOTE: this is in contrast to the iCal spec which says until should be the
             //       dtstart of the last occurence. But as the client with the name of the
             //       spec sets it to the end of the day, we do it also.
             if ($rrule->until instanceof Tinebase_DateTime && !$this->is_all_day_event) {
                 $rrule->until->setTimezone($this->originator_tz);
                 // NOTE: subSecond cause some clients send 00:00:00 for midnight
                 $rrule->until->subSecond(1)->setTime(23, 59, 59);
                 $rrule->until->setTimezone('UTC');
             }
             $this->rrule_until = $rrule->until;
         }
     }
     if ($this->rrule_until && $this->rrule_until->getTimeStamp() - $this->dtstart->getTimeStamp() < -1) {
         throw new Tinebase_Exception_Record_Validation('rrule until must not be before dtstart');
     }
 }
Ejemplo n.º 4
0
 /**
  * sets rrule until helper field
  *
  * @return void
  */
 public function setRruleUntil()
 {
     if (empty($this->rrule)) {
         $this->rrule_until = NULL;
     } else {
         $rrule = $this->rrule;
         if (!$this->rrule instanceof Calendar_Model_Rrule) {
             $rrule = new Calendar_Model_Rrule(array());
             $rrule->setFromString($this->rrule);
         }
         if (isset($rrule->count)) {
             $this->rrule_until = NULL;
             $exdates = $this->exdate;
             $this->exdate = NULL;
             $lastOccurrence = Calendar_Model_Rrule::computeNextOccurrence($this, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $this->dtend, $rrule->count - 1);
             $this->rrule_until = $lastOccurrence->dtend;
             $this->exdate = $exdates;
         } else {
             $this->rrule_until = $rrule->until;
         }
     }
 }