Also move recurrence computation classes to libcalendaring
This commit is contained in:
parent
68e7adfa04
commit
70818e4998
6 changed files with 166 additions and 73 deletions
|
@ -1,15 +1,15 @@
|
|||
<?php
|
||||
|
||||
require_once realpath(__DIR__ . '/../../libcalendaring/lib/libcalendaring_recurrence.php');
|
||||
|
||||
/**
|
||||
* Recurrence computation class for the Calendar plugin
|
||||
*
|
||||
* Uitility class to compute instances of recurring events.
|
||||
*
|
||||
* @version @package_version@
|
||||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||
* @package @package_name@
|
||||
*
|
||||
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
||||
* Copyright (C) 2012-2014, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -24,14 +24,10 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
class calendar_recurrence
|
||||
class calendar_recurrence extends libcalendaring_recurrence
|
||||
{
|
||||
private $cal;
|
||||
private $event;
|
||||
private $next;
|
||||
private $engine;
|
||||
private $duration;
|
||||
private $hour = 0;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
|
@ -41,62 +37,15 @@ class calendar_recurrence
|
|||
*/
|
||||
function __construct($cal, $event)
|
||||
{
|
||||
// use Horde classes to compute recurring instances
|
||||
// TODO: replace with something that has less than 6'000 lines of code
|
||||
require_once(__DIR__ . '/Horde_Date_Recurrence.php');
|
||||
parent::__construct($cal->lib);
|
||||
|
||||
$this->cal = $cal;
|
||||
$this->event = $event;
|
||||
$this->next = new Horde_Date($event['start'], $cal->timezone->getName());
|
||||
$this->hour = $this->next->hour;
|
||||
|
||||
if (is_object($event['start']) && is_object($event['end']))
|
||||
$this->duration = $event['start']->diff($event['end']);
|
||||
|
||||
$this->engine = new Horde_Date_Recurrence($event['start']);
|
||||
$this->engine->fromRRule20(libcalendaring::to_rrule($event['recurrence']));
|
||||
|
||||
if (is_array($event['recurrence']['EXDATE'])) {
|
||||
foreach ($event['recurrence']['EXDATE'] as $exdate) {
|
||||
if (is_a($exdate, 'DateTime')) {
|
||||
$this->engine->addException($exdate->format('Y'), $exdate->format('n'), $exdate->format('j'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_array($event['recurrence']['RDATE'])) {
|
||||
foreach ($event['recurrence']['RDATE'] as $rdate) {
|
||||
if (is_a($rdate, 'DateTime')) {
|
||||
$this->engine->addRDate($rdate->format('Y'), $rdate->format('n'), $rdate->format('j'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date/time of the next occurence of this event
|
||||
*
|
||||
* @return mixed DateTime object or False if recurrence ended
|
||||
*/
|
||||
public function next_start()
|
||||
{
|
||||
$time = false;
|
||||
$after = clone $this->next;
|
||||
$after->mday = $after->mday + 1;
|
||||
if ($this->next && ($next = $this->engine->nextActiveRecurrence($after))) {
|
||||
if (!$next->after($this->next)) {
|
||||
// avoid endless loops if recurrence computation fails
|
||||
return false;
|
||||
}
|
||||
if ($this->event['allday']) {
|
||||
$next->hour = $this->hour; # fix time for all-day events
|
||||
$next->min = 0;
|
||||
}
|
||||
|
||||
$time = $next->toDateTime();
|
||||
$this->next = $next;
|
||||
}
|
||||
|
||||
return $time;
|
||||
$event['start']->_dateonly |= $event['allday'];
|
||||
$this->init($event['recurrence'], $event['start']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,13 +56,15 @@ class calendar_recurrence
|
|||
public function next_instance()
|
||||
{
|
||||
if ($next_start = $this->next_start()) {
|
||||
$next_end = clone $next_start;
|
||||
$next_end->add($this->duration);
|
||||
|
||||
$next = $this->event;
|
||||
$next['recurrence_id'] = $next_start->format('Y-m-d');
|
||||
$next['start'] = $next_start;
|
||||
$next['end'] = $next_end;
|
||||
|
||||
if ($this->duration) {
|
||||
$next['end'] = clone $next_start;
|
||||
$next['end']->add($this->duration);
|
||||
}
|
||||
|
||||
unset($next['_formatobj']);
|
||||
|
||||
return $next;
|
||||
|
|
|
@ -56,17 +56,10 @@
|
|||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
</file>
|
||||
<file name="lib/calendar_recurrence.php" role="php">
|
||||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
</file>
|
||||
<file name="lib/calendar_ui.php" role="php">
|
||||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
</file>
|
||||
<file name="lib/Horde_Date.php" role="php"></file>
|
||||
<file name="lib/Horde_Date_Recurrence.php" role="php"></file>
|
||||
<file name="lib/Horde_iCalendar.php" role="php"></file>
|
||||
<file name="lib/fullcalendar-rc.patch" role="data">
|
||||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
|
@ -75,10 +68,6 @@
|
|||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
</file>
|
||||
<file name="lib/jquery.miniColors.min.js" role="data">
|
||||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
</file>
|
||||
<file name="drivers/calendar_driver.php" role="php">
|
||||
<tasks:replace from="@name@" to="name" type="package-info"/>
|
||||
<tasks:replace from="@package_version@" to="version" type="package-info"/>
|
||||
|
|
143
plugins/libcalendaring/lib/libcalendaring_recurrence.php
Normal file
143
plugins/libcalendaring/lib/libcalendaring_recurrence.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Recurrence computation class for shared use
|
||||
*
|
||||
* Uitility class to compute reccurrence dates from the given rules
|
||||
*
|
||||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2012-2014, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
class libcalendaring_recurrence
|
||||
{
|
||||
protected $lib;
|
||||
protected $start;
|
||||
protected $next;
|
||||
protected $engine;
|
||||
protected $recurrence;
|
||||
protected $dateonly = false;
|
||||
protected $hour = 0;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param object calendar The calendar plugin instance
|
||||
*/
|
||||
function __construct($lib)
|
||||
{
|
||||
// use Horde classes to compute recurring instances
|
||||
// TODO: replace with something that has less than 6'000 lines of code
|
||||
require_once(__DIR__ . '/Horde_Date_Recurrence.php');
|
||||
|
||||
$this->lib = $lib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize recurrence engine
|
||||
*
|
||||
* @param array The recurrence properties
|
||||
* @param object DateTime The recurrence start date
|
||||
*/
|
||||
public function init($recurrence, $start)
|
||||
{
|
||||
$this->start = $start;
|
||||
$this->recurrence = $recurrence;
|
||||
$this->dateonly = $start->_dateonly;
|
||||
$this->next = new Horde_Date($start, $this->lib->timezone->getName());
|
||||
$this->hour = $this->next->hour;
|
||||
|
||||
$this->engine = new Horde_Date_Recurrence($start);
|
||||
$this->engine->fromRRule20(libcalendaring::to_rrule($recurrence));
|
||||
|
||||
if (is_array($recurrence['EXDATE'])) {
|
||||
foreach ($recurrence['EXDATE'] as $exdate) {
|
||||
if (is_a($exdate, 'DateTime')) {
|
||||
$this->engine->addException($exdate->format('Y'), $exdate->format('n'), $exdate->format('j'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_array($recurrence['RDATE'])) {
|
||||
foreach ($recurrence['RDATE'] as $rdate) {
|
||||
if (is_a($rdate, 'DateTime')) {
|
||||
$this->engine->addRDate($rdate->format('Y'), $rdate->format('n'), $rdate->format('j'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date/time of the next occurence of this event
|
||||
*
|
||||
* @return mixed DateTime object or False if recurrence ended
|
||||
*/
|
||||
public function next_start()
|
||||
{
|
||||
$time = false;
|
||||
$after = clone $this->next;
|
||||
$after->mday = $after->mday + 1;
|
||||
if ($this->next && ($next = $this->engine->nextActiveRecurrence($after))) {
|
||||
// avoid endless loops if recurrence computation fails
|
||||
if (!$next->after($this->next)) {
|
||||
return false;
|
||||
}
|
||||
// fix time for all-day events
|
||||
if ($this->dateonly) {
|
||||
$next->hour = $this->hour;
|
||||
$next->min = 0;
|
||||
}
|
||||
|
||||
$time = $next->toDateTime();
|
||||
$this->next = $next;
|
||||
}
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end date of the occurence of this recurrence cycle
|
||||
*
|
||||
* @return DateTime|bool End datetime of the last occurence or False if recurrence exceeds limit
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
// recurrence end date is given
|
||||
if ($this->recurrence['UNTIL'] instanceof DateTime) {
|
||||
return $this->recurrence['UNTIL'];
|
||||
}
|
||||
|
||||
// take the last RDATE entry if set
|
||||
if (is_array($this->recurrence['RDATE']) && !empty($this->recurrence['RDATE'])) {
|
||||
$last = end($this->recurrence['RDATE']);
|
||||
if ($last instanceof DateTime) {
|
||||
return $last;
|
||||
}
|
||||
}
|
||||
|
||||
// run through all items till we reach the end
|
||||
if ($this->recurrence['COUNT']) {
|
||||
$last = $this->start;
|
||||
$this->next = new Horde_Date($this->start, $this->lib->timezone->getName());
|
||||
while (($next = $this->next_start()) && $c < 1000) {
|
||||
$last = $next;
|
||||
$c++;
|
||||
}
|
||||
}
|
||||
|
||||
return $last;
|
||||
}
|
||||
|
||||
}
|
|
@ -124,6 +124,16 @@ class libcalendaring extends rcube_plugin
|
|||
return new libcalendaring_itip($self, $domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load recurrence computation engine
|
||||
*/
|
||||
public static function get_recurrence()
|
||||
{
|
||||
$self = self::get_instance();
|
||||
require_once($self->home . '/lib/libcalendaring_recurrence.php');
|
||||
return new libcalendaring_recurrence($self);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift dates into user's current timezone
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue