Retrieves all the completions for this event.
public getCompletions ( ) : array | ||
return | array | Array containing the dates of all the completions in YYYYMMDD form. |
/** * Toggles completion status of this task. Moves a recurring task * to the next occurence on completion. */ public function toggleComplete() { if ($this->completed) { $this->completed_date = null; $this->completed = false; if ($this->recurs()) { /* What do we want do delete here? All completions? * The latest completion? Any completion in the * future?. */ foreach ($this->recurrence->getCompletions() as $completion) { $this->recurrence->deleteCompletion(substr($completion, 0, 4), substr($completion, 4, 2), substr($completion, 6, 2)); } } return; } if ($this->recurs()) { /* Get current occurrence (task due date) */ $current = $this->recurrence->nextActiveRecurrence(new Horde_Date($this->due)); if ($current) { $this->recurrence->addCompletion($current->year, $current->month, $current->mday); /* Advance this occurence by a day to indicate that we * want the following occurence (Recurrence uses days * as minimal time duration between occurrences). */ $current->mday++; /* Only mark this due date completed if there is another * occurence. */ if ($next = $this->recurrence->nextActiveRecurrence($current)) { $this->completed = false; return; } } } $this->completed_date = time(); $this->completed = true; }
/** * Returns the next start date of this task. * * Takes recurring tasks into account. * * @return Horde_Date The next start date. */ public function getNextStart() { if (!$this->start) { return null; } if (!$this->recurs() || !($completions = $this->recurrence->getCompletions())) { return new Horde_Date($this->start); } sort($completions); list($year, $month, $mday) = sscanf(end($completions), '%04d%02d%02d'); $lastCompletion = new Horde_Date($year, $month, $mday); $recurrence = clone $this->recurrence; $recurrence->start = new Horde_Date($this->start); return $recurrence->nextRecurrence($lastCompletion); }
/** * Exports this task in iCalendar format. * * @param Horde_Icalendar $calendar A Horde_Icalendar object that acts as * the container. * * @return Horde_Icalendar_Vtodo A vtodo component of this task. */ public function toiCalendar(Horde_Icalendar $calendar) { $vTodo = Horde_Icalendar::newComponent('vtodo', $calendar); $v1 = $calendar->getAttribute('VERSION') == '1.0'; $vTodo->setAttribute('UID', $this->uid); if (!empty($this->assignee)) { $vTodo->setAttribute('ATTENDEE', Nag::getUserEmail($this->assignee), array('ROLE' => 'REQ-PARTICIPANT')); } $vTodo->setAttribute('ORGANIZER', !empty($this->organizer) ? Nag::getUserEmail($this->organizer) : Nag::getUserEmail($this->owner)); if (!empty($this->name)) { $vTodo->setAttribute('SUMMARY', $this->name); } if (!empty($this->desc)) { $vTodo->setAttribute('DESCRIPTION', $this->desc); } if (isset($this->priority)) { $vTodo->setAttribute('PRIORITY', $this->priority); } if (!empty($this->parent_id) && !empty($this->parent)) { $vTodo->setAttribute('RELATED-TO', $this->parent->uid); } if ($this->private) { $vTodo->setAttribute('CLASS', 'PRIVATE'); } if (!empty($this->start)) { $vTodo->setAttribute('DTSTART', $this->start); } if ($this->due) { $vTodo->setAttribute('DUE', $this->due); if ($this->alarm) { if ($v1) { $vTodo->setAttribute('AALARM', $this->due - $this->alarm * 60); } else { $vAlarm = Horde_Icalendar::newComponent('valarm', $vTodo); $vAlarm->setAttribute('ACTION', 'DISPLAY'); $vAlarm->setAttribute('TRIGGER;VALUE=DURATION', '-PT' . $this->alarm . 'M'); $vTodo->addComponent($vAlarm); } } } if ($this->completed) { $vTodo->setAttribute('STATUS', 'COMPLETED'); $vTodo->setAttribute('COMPLETED', $this->completed_date ? $this->completed_date : $_SERVER['REQUEST_TIME']); $vTodo->setAttribute('PERCENT-COMPLETE', '100'); } else { if (!empty($this->estimate)) { $vTodo->setAttribute('PERCENT-COMPLETE', $this->actual / $this->estimate * 100); } if ($v1) { $vTodo->setAttribute('STATUS', 'NEEDS ACTION'); } else { $vTodo->setAttribute('STATUS', 'NEEDS-ACTION'); } } // Recurrence. // We may have to implicitely set DTSTART if not set explicitely, may // some clients choke on missing DTSTART attributes while RRULE exists. if ($this->recurs()) { if ($v1) { $rrule = $this->recurrence->toRRule10($calendar); } else { $rrule = $this->recurrence->toRRule20($calendar); } if (!empty($rrule)) { $vTodo->setAttribute('RRULE', $rrule); } /* The completions represent deleted recurrences */ foreach ($this->recurrence->getCompletions() as $exception) { if (!empty($exception)) { // Use multiple EXDATE attributes instead of EXDATE // attributes with multiple values to make Apple iCal // happy. list($year, $month, $mday) = sscanf($exception, '%04d%02d%02d'); $vTodo->setAttribute('EXDATE', array(new Horde_Date($year, $month, $mday)), array('VALUE' => 'DATE')); } } } if ($this->tags) { $vTodo->setAttribute('CATEGORIES', implode(', ', $this->tags)); } /* Get the task's history. */ $created = $modified = null; try { $log = $GLOBALS['injector']->getInstance('Horde_History')->getHistory('nag:' . $this->tasklist . ':' . $this->uid); foreach ($log as $entry) { switch ($entry['action']) { case 'add': $created = $entry['ts']; break; case 'modify': $modified = $entry['ts']; break; } } } catch (Exception $e) { } if (!empty($created)) { $vTodo->setAttribute($v1 ? 'DCREATED' : 'CREATED', $created); if (empty($modified)) { $modified = $created; } } if (!empty($modified)) { $vTodo->setAttribute('LAST-MODIFIED', $modified); } return $vTodo; }
/** */ public function testCompletions() { $r = new Horde_Date_Recurrence(new Horde_Date(1970, 1, 1)); $r->setRecurType(Horde_Date_Recurrence::RECUR_DAILY); $r->addCompletion(1970, 1, 2); $this->assertTrue($r->hasCompletion(1970, 1, 2)); $this->assertEquals(1, count($r->getCompletions())); $r->addCompletion(1970, 1, 4); $this->assertEquals(2, count($r->getCompletions())); $r->deleteCompletion(1970, 1, 2); $this->assertEquals(1, count($r->getCompletions())); $this->assertFalse($r->hasCompletion(1970, 1, 2)); $r->addCompletion(1970, 1, 2); $r->addException(1970, 1, 1); $r->addException(1970, 1, 3); $next = $r->nextRecurrence(new Horde_Date($r->start)); $this->assertEquals(1, $next->mday); $this->assertTrue($r->hasException($next->year, $next->month, $next->mday)); $next->mday++; $next = $r->nextRecurrence($next); $this->assertTrue($r->hasCompletion($next->year, $next->month, $next->mday)); $next->mday++; $next = $r->nextRecurrence($next); $this->assertTrue($r->hasException($next->year, $next->month, $next->mday)); $next->mday++; $next = $r->nextRecurrence($next); $this->assertTrue($r->hasCompletion($next->year, $next->month, $next->mday)); $r->setRecurEnd(new Horde_Date(1970, 1, 4)); $this->assertTrue($r->hasRecurEnd()); $this->assertFalse($r->hasActiveRecurrence()); $s = new Horde_Date_Recurrence(new Horde_Date(1970, 1, 1)); $s->fromKolab($r->toKolab()); $this->assertTrue($s->hasRecurEnd()); $next = $s->nextRecurrence(new Horde_Date($s->start)); $this->assertEquals(1, $next->mday); $this->assertTrue($s->hasException($next->year, $next->month, $next->mday)); $next->mday++; $next = $s->nextRecurrence($next); $this->assertTrue($s->hasCompletion($next->year, $next->month, $next->mday)); $next->mday++; $next = $s->nextRecurrence($next); $this->assertTrue($s->hasException($next->year, $next->month, $next->mday)); $next->mday++; $next = $s->nextRecurrence($next); $this->assertTrue($s->hasCompletion($next->year, $next->month, $next->mday)); $this->assertEquals(2, count($s->getCompletions())); $this->assertEquals(2, count($s->getExceptions())); $this->assertFalse($s->hasActiveRecurrence()); $this->assertEquals(2, count($s->getCompletions())); $s->deleteCompletion(1970, 1, 2); $this->assertEquals(1, count($s->getCompletions())); $s->deleteCompletion(1970, 1, 4); $this->assertEquals(0, count($s->getCompletions())); }