/** * testImportRruleNormalize * * @see 0009856: ics import: recurring events one day earlier */ public function testImportRruleNormalize() { $importer = new Calendar_Import_Ical(array('container_id' => $this->_getTestCalendar()->getId())); $importer->importFile(dirname(__FILE__) . '/files/ni-zsk.ics'); // fetch first of may in 2014 $from = new Tinebase_DateTime('2014-04-23 22:00:00'); $until = new Tinebase_DateTime('2014-05-23 22:00:00'); $events = Calendar_Controller_Event::getInstance()->search(new Calendar_Model_EventFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_getTestCalendar()->getId()), array('field' => 'period', 'operator' => 'within', 'value' => array('from' => $from->toString(), 'until' => $until->toString())))), NULL); Calendar_Model_Rrule::mergeRecurrenceSet($events, $from, $until); $firstOfMay2014 = $events[1]; $this->assertEquals('2014-04-30 22:00:00', $firstOfMay2014->dtstart); }
/** * returns feast days as array containing Tinebase_DateTime objects * if the period exceeds the contracts' period(s), the contracts' period(s) will be used * * @param HumanResources_Model_Contract|Tinebase_Record_RecordSet $contracts * @param Tinebase_DateTime $firstDate * @param Tinebase_DateTime $lastDate * @return array */ public function getFeastDays($contracts, Tinebase_DateTime $firstDate, Tinebase_DateTime $lastDate) { $contracts = $this->_convertToRecordSet($contracts); $dates = array(); foreach ($contracts as $contract) { $fd = $this->_getFirstDate($contract, $firstDate); $ld = $this->_getLastDate($contract, $lastDate); // on calendar search we have to do this to get the right interval: $fd->subSecond(1); $ld->addSecond(1); $periodFilter = new Calendar_Model_PeriodFilter(array('field' => 'period', 'operator' => 'within', 'value' => array('from' => $fd, 'until' => $ld))); $events = Calendar_Controller_Event::getInstance()->search(new Calendar_Model_EventFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $contract->feast_calendar_id)))); Calendar_Model_Rrule::mergeRecurrenceSet($events, $fd, $ld); $events->setTimezone(Tinebase_Core::getUserTimezone()); foreach ($events as $event) { if (!$event->isInPeriod($periodFilter)) { continue; } if ($event->is_all_day_event) { $days = round(($event->dtend->getTimestamp() - $event->dtstart->getTimestamp()) / 86400); $i = 0; while ($i < $days) { $dateOfEvent = clone $event->dtstart; $dateOfEvent->addDay($i); $dates[] = $dateOfEvent; $i++; } } else { $dates[] = $event->dtstart; } } } return array_unique($dates); }
public function testCreateRecurExceptionWithEditGrantOnly() { $this->markTestIncomplete('temporarily disabled until fixed'); // set testuser to have editgrant for sclever Tinebase_Container::getInstance()->setGrants($this->_getPersonasDefaultCals('sclever'), new Tinebase_Record_RecordSet('Tinebase_Model_Grants', array(array('account_id' => $this->_getPersona('sclever')->getId(), 'account_type' => 'user', Tinebase_Model_Grants::GRANT_READ => true, Tinebase_Model_Grants::GRANT_ADD => true, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => true, Tinebase_Model_Grants::GRANT_PRIVATE => true, Tinebase_Model_Grants::GRANT_ADMIN => true, Tinebase_Model_Grants::GRANT_FREEBUSY => true), array('account_id' => Tinebase_Core::getUser()->getId(), 'account_type' => 'user', Tinebase_Model_Grants::GRANT_READ => false, Tinebase_Model_Grants::GRANT_ADD => false, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => false, Tinebase_Model_Grants::GRANT_PRIVATE => false, Tinebase_Model_Grants::GRANT_ADMIN => false, Tinebase_Model_Grants::GRANT_FREEBUSY => false))), TRUE); $persistentEvent = $this->_createEventInPersonasCalendar('sclever', 'sclever'); $persistentEvent->rrule = 'FREQ=DAILY;INTERVAL=1'; $updatedEvent = $this->_uit->update($persistentEvent); $events = $this->_uit->search(new Calendar_Model_EventFilter(array(array('field' => 'id', 'operator' => 'equals', 'value' => $persistentEvent->getId()))), NULL, FALSE, FALSE); $this->assertEquals(1, count($events), 'failed to search fb event'); Calendar_Model_Rrule::mergeRecurrenceSet($events, $updatedEvent->dtstart, $updatedEvent->dtstart->getClone()->addDay(7)); $this->assertEquals(8, count($events), 'failed to merge recurrence set'); $events[3]->summary = 'exception'; $exception = $this->_uit->createRecurException($events[3]); $this->assertEquals('exception', $exception->summary); }
/** * @see #5806: thisandfuture range updates with count part fail */ public function testCreateRecurExceptionAllFollowingWithCount() { $from = new Tinebase_DateTime('2012-02-20 00:00:00'); $until = new Tinebase_DateTime('2012-02-26 23:59:59'); $event = new Calendar_Model_Event(array('uid' => Tinebase_Record_Abstract::generateUID(), 'summary' => 'Abendessen', 'dtstart' => '2012-02-21 14:00:00', 'dtend' => '2012-02-21 15:30:00', 'originator_tz' => 'Europe/Berlin', 'rrule' => 'FREQ=DAILY;COUNT=5', 'container_id' => $this->_testCalendar->getId())); $persistentEvent = $this->_controller->create($event); // create exception $weekviewEvents = $this->_controller->search(new Calendar_Model_EventFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId())))); Calendar_Model_Rrule::mergeRecurrenceSet($weekviewEvents, $from, $until); $weekviewEvents[2]->dtstart->subHour(5); $weekviewEvents[2]->dtend->subHour(5); $this->_controller->createRecurException($weekviewEvents[2], FALSE, TRUE); // load events $weekviewEvents = $this->_controller->search(new Calendar_Model_EventFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId())))); Calendar_Model_Rrule::mergeRecurrenceSet($weekviewEvents, $from, $until); $weekviewEvents->sort('dtstart', 'ASC'); $this->assertEquals(2, count($weekviewEvents->filter('uid', $weekviewEvents[0]->uid)), 'shorten failed'); $this->assertEquals(5, count($weekviewEvents), 'wrong total count'); }
/** * returns freebusy information for given period and given attendee * * @todo merge overlapping events to one freebusy entry * * @param array of array with from and until $_periods * @param Tinebase_Record_RecordSet of Calendar_Model_Attender $_attendee * @param array of UIDs $_ignoreUIDs * @return Tinebase_Record_RecordSet of Calendar_Model_FreeBusy */ public function getFreeBusyInfo($_periods, $_attendee, $_ignoreUIDs = array()) { $fbInfoSet = new Tinebase_Record_RecordSet('Calendar_Model_FreeBusy'); // map groupmembers to users $attendee = clone $_attendee; $attendee->addIndices(array('user_type')); $groupmembers = $attendee->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER); $groupmembers->user_type = Calendar_Model_Attender::USERTYPE_USER; // base filter data $filterData = array(array('field' => 'attender', 'operator' => 'in', 'value' => $_attendee), array('field' => 'transp', 'operator' => 'equals', 'value' => Calendar_Model_Event::TRANSP_OPAQUE)); // add all periods to filterdata $periodFilters = array(); foreach ($_periods as $period) { $periodFilters[] = array('field' => 'period', 'operator' => 'within', 'value' => array('from' => $period['from'], 'until' => $period['until'])); } $filterData[] = array('condition' => 'OR', 'filters' => $periodFilters); // finaly create filter $filter = new Calendar_Model_EventFilter($filterData); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . ' ' . __LINE__ . ' free/busy filter: ' . print_r($filter->toArray(), true)); } $events = $this->search($filter, new Tinebase_Model_Pagination(), FALSE, FALSE); foreach ($_periods as $period) { Calendar_Model_Rrule::mergeRecurrenceSet($events, $period['from'], $period['until']); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . ' ' . __LINE__ . ' value: ' . print_r($events->toArray(), true)); } // create a typemap $typeMap = array(); foreach ($attendee as $attender) { if (!(isset($typeMap[$attender['user_type']]) || array_key_exists($attender['user_type'], $typeMap))) { $typeMap[$attender['user_type']] = array(); } $typeMap[$attender['user_type']][$attender['user_id']] = array(); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . ' ' . __LINE__ . ' value: ' . print_r($typeMap, true)); } // generate freeBusyInfos foreach ($events as $event) { // skip events with ignoreUID if (in_array($event->uid, $_ignoreUIDs)) { continue; } // check if event is conflicting one of the given periods $conflicts = FALSE; foreach ($_periods as $period) { if ($event->dtstart->isEarlier($period['until']) && $event->dtend->isLater($period['from'])) { $conflicts = TRUE; break; } } if (!$conflicts) { continue; } // map groupmembers to users $event->attendee->addIndices(array('user_type')); $groupmembers = $event->attendee->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER); $groupmembers->user_type = Calendar_Model_Attender::USERTYPE_USER; foreach ($event->attendee as $attender) { // skip declined/transp events if ($attender->status == Calendar_Model_Attender::STATUS_DECLINED || $attender->transp == Calendar_Model_Event::TRANSP_TRANSP) { continue; } if ((isset($typeMap[$attender->user_type]) || array_key_exists($attender->user_type, $typeMap)) && (isset($typeMap[$attender->user_type][$attender->user_id]) || array_key_exists($attender->user_id, $typeMap[$attender->user_type]))) { $fbInfo = new Calendar_Model_FreeBusy(array('user_type' => $attender->user_type, 'user_id' => $attender->user_id, 'dtstart' => clone $event->dtstart, 'dtend' => clone $event->dtend, 'type' => Calendar_Model_FreeBusy::FREEBUSY_BUSY), true); if ($event->{Tinebase_Model_Grants::GRANT_READ}) { $fbInfo->event = clone $event; unset($fbInfo->event->attendee); } //$typeMap[$attender->user_type][$attender->user_id][] = $fbInfo; $fbInfoSet->addRecord($fbInfo); } } } return $fbInfoSet; }
/** * returns conflicting periods * * @param Calendar_Model_EventFilter $periodCandidates * @param Calendar_Model_EventFilter $conflictCriteria * @param bool $getAll * @return array */ public function getConflictingPeriods($periodCandidates, $conflictCriteria, $getAll = false) { $conflictFilter = clone $conflictCriteria; $conflictFilter->addFilterGroup($periodCandidates); $conflictCandidates = $this->search($conflictFilter); $from = Tinebase_DateTime::now(); $until = Tinebase_DateTime::now(); foreach ($periodCandidates as $periodFilter) { $period = $periodFilter->getValue(); $from = min($from, $period['from']); $until = max($until, $period['until']); // Calendar_Model_Rrule::mergeRecurrenceSet($conflictCandidates, $period['from'], $period['until']); } Calendar_Model_Rrule::mergeRecurrenceSet($conflictCandidates, $from, $until); $conflicts = array(); foreach ($periodCandidates as $periodFilter) { $period = $periodFilter->getValue(); foreach ($conflictCandidates as $event) { if ($event->dtstart->isEarlier($period['until']) && $event->dtend->isLater($period['from'])) { $conflicts[] = array('from' => $period['from'], 'until' => $period['until'], 'event' => $event); if (!$getAll) { break; } } } } return $conflicts; }