Fix libcalendaring_recurrence::end()

This commit is contained in:
Aleksander Machniak 2022-12-02 15:57:59 +01:00
parent e4271ccfd8
commit a9531c9336
5 changed files with 192 additions and 54 deletions

View file

@ -143,24 +143,24 @@ class libcalendaring_recurrence
return $this->recurrence['UNTIL'];
}
if (!$this->engine->isInfinite()) {
// run through all items till we reach the end
try {
foreach ($this->engine as $end) {
// do nothing
}
}
catch (Exception $e) {
// Run through all items till we reach the end, or limit of iterations
// Note: Sabre has a limits of iteration in VObject\Settings, so it is not an infinite loop
try {
foreach ($this->engine as $end) {
// do nothing
}
}
else if (isset($this->event['end']) && $this->event['end'] instanceof DateTimeInterface) {
catch (Exception $e) {
// do nothing
}
/*
if (empty($end) && isset($this->event['start']) && $this->event['start'] instanceof DateTimeInterface) {
// determine a reasonable end date if none given
$end = clone $this->event['end'];
$end = clone $this->event['start'];
$end->add(new DateInterval('P100Y'));
}
return isset($end) ? $this->toDateTime($end, false) : false;
*/
return isset($end) ? $this->toDateTime($end) : false;
}
/**

View file

@ -34,25 +34,55 @@ class RecurrenceTest extends PHPUnit\Framework\TestCase
}
/**
* Test for libcalendaring_recurrence::first_occurrence()
*
* @dataProvider data_first_occurrence
* Data for test_end()
*/
function test_first_occurrence($recurrence_data, $start, $expected)
function data_end()
{
$start = new DateTime($start);
if (!empty($recurrence_data['UNTIL'])) {
$recurrence_data['UNTIL'] = new DateTime($recurrence_data['UNTIL']);
}
return [
// non-recurring
[
[
'recurrence' => [],
'start' => new DateTime('2017-08-31 11:00:00')
],
'2017-08-31 11:00:00', // expected result
],
// daily
[
[
'recurrence' => ['FREQ' => 'DAILY', 'INTERVAL' => '1', 'COUNT' => 2],
'start' => new DateTime('2017-08-31 11:00:00')
],
'2017-09-01 11:00:00',
],
// weekly
[
[
'recurrence' => ['FREQ' => 'WEEKLY', 'COUNT' => 3],
'start' => new DateTime('2017-08-31 11:00:00'), // Thursday
],
'2017-09-14 11:00:00',
],
// UNTIL
[
[
'recurrence' => ['FREQ' => 'WEEKLY', 'COUNT' => 3, 'UNTIL' => new DateTime('2017-09-07 11:00:00')],
'start' => new DateTime('2017-08-31 11:00:00'), // Thursday
],
'2017-09-07 11:00:00',
],
// Infinite recurrence, no count, no until
[
[
'recurrence' => ['FREQ' => 'WEEKLY', 'INTERVAL' => '1'],
'start' => new DateTime('2017-08-31 11:00:00'), // Thursday
],
'2084-09-21 11:00:00',
],
$recurrence = $this->plugin->get_recurrence();
$recurrence->init($recurrence_data, $start);
$first = $recurrence->first_occurrence();
$this->assertEquals($expected, $first ? $first->format('Y-m-d H:i:s') : '');
// TODO: Test an event with EXDATE/RDATEs
];
}
/**
* Data for test_first_occurrence()
*/
@ -223,6 +253,40 @@ class RecurrenceTest extends PHPUnit\Framework\TestCase
);
}
/**
* Test for libcalendaring_recurrence::end()
*
* @dataProvider data_end
*/
function test_end($event, $expected)
{
$recurrence = new libcalendaring_recurrence($this->plugin, $event);
$end = $recurrence->end();
$this->assertSame($expected, $end ? $end->format('Y-m-d H:i:s') : $end);
}
/**
* Test for libcalendaring_recurrence::first_occurrence()
*
* @dataProvider data_first_occurrence
*/
function test_first_occurrence($recurrence_data, $start, $expected)
{
$start = new DateTime($start);
if (!empty($recurrence_data['UNTIL'])) {
$recurrence_data['UNTIL'] = new DateTime($recurrence_data['UNTIL']);
}
$recurrence = $this->plugin->get_recurrence();
$recurrence->init($recurrence_data, $start);
$first = $recurrence->first_occurrence();
$this->assertEquals($expected, $first ? $first->format('Y-m-d H:i:s') : '');
}
/**
* Test for libcalendaring_recurrence::first_occurrence() for all-day events
*

View file

@ -128,7 +128,7 @@ class kolab_date_recurrence
$event = $this->object->to_array();
// recurrence end date is given
if ($event['recurrence']['UNTIL'] instanceof DateTimeInterface) {
if (isset($event['recurrence']['UNTIL']) && $event['recurrence']['UNTIL'] instanceof DateTimeInterface) {
return $event['recurrence']['UNTIL'];
}
@ -139,12 +139,13 @@ class kolab_date_recurrence
return $end_dt;
}
// determine a reasonable end date if none given
if (!$event['recurrence']['COUNT'] && $event['end'] instanceof DateTimeInterface) {
$end_dt = clone $event['end'];
$end_dt->add(new DateInterval('P100Y'));
return $end_dt;
// determine a reasonable end date for an infinite recurrence
if (empty($event['recurrence']['COUNT'])) {
if (!empty($event['start']) && $event['start'] instanceof DateTimeInterface) {
$start_dt = clone $event['start'];
$start_dt->add(new DateInterval('P100Y'));
return $start_dt;
}
}
return false;

View file

@ -37,6 +37,7 @@ class libkolab extends rcube_plugin
{
// load local config
$this->load_config();
$this->require_plugin('libcalendaring');
// extend include path to load bundled lib classes
$include_path = $this->home . '/lib' . PATH_SEPARATOR . ini_get('include_path');

View file

@ -27,32 +27,58 @@ class KolabDateRecurrenceTest extends PHPUnit\Framework\TestCase
{
$rcube = rcmail::get_instance();
$rcube->plugins->load_plugin('libkolab', true, true);
$rcube->plugins->load_plugin('libcalendaring', true, true);
}
/**
* kolab_date_recurrence::first_occurrence()
*
* @dataProvider data_first_occurrence
* Data for test_end()
*/
function test_first_occurrence($recurrence_data, $start, $expected)
function data_end()
{
if (!kolab_format::supports(3)) {
$this->markTestSkipped('No Kolab support');
}
return [
// non-recurring
[
[
'recurrence' => [],
'start' => new DateTime('2017-08-31 11:00:00')
],
'2117-08-31 11:00:00', // expected result
],
// daily
[
[
'recurrence' => ['FREQ' => 'DAILY', 'INTERVAL' => '1', 'COUNT' => 2],
'start' => new DateTime('2017-08-31 11:00:00')
],
'2017-09-01 11:00:00',
],
// weekly
[
[
'recurrence' => ['FREQ' => 'WEEKLY', 'INTERVAL' => '1', 'COUNT' => 3],
'start' => new DateTime('2017-08-31 11:00:00'), // Thursday
],
'2017-09-14 11:00:00',
],
// UNTIL
[
[
'recurrence' => ['FREQ' => 'WEEKLY', 'INTERVAL' => '1', 'COUNT' => 3, 'UNTIL' => new DateTime('2017-09-07 11:00:00')],
'start' => new DateTime('2017-08-31 11:00:00'), // Thursday
],
'2017-09-07 11:00:00',
],
// Infinite recurrence, no count, no until
[
[
'recurrence' => ['FREQ' => 'WEEKLY', 'INTERVAL' => '1'],
'start' => new DateTime('2017-08-31 11:00:00'), // Thursday
],
'2117-08-31 11:00:00',
],
$start = new DateTime($start);
if (!empty($recurrence_data['UNTIL'])) {
$recurrence_data['UNTIL'] = new DateTime($recurrence_data['UNTIL']);
}
$event = array('start' => $start, 'recurrence' => $recurrence_data);
$object = kolab_format::factory('event', 3.0);
$object->set($event);
$recurrence = new kolab_date_recurrence($object);
$first = $recurrence->first_occurrence();
$this->assertEquals($expected, $first ? $first->format('Y-m-d H:i:s') : '');
// TODO: Test an event with EXDATE/RDATE
];
}
/**
@ -213,6 +239,52 @@ class KolabDateRecurrenceTest extends PHPUnit\Framework\TestCase
);
}
/**
* kolab_date_recurrence::end()
*
* @dataProvider data_end
*/
function test_end($event, $expected)
{
if (!kolab_format::supports(3)) {
$this->markTestSkipped('No Kolab support');
}
$object = kolab_format::factory('event', 3.0);
$object->set($event);
$recurrence = new kolab_date_recurrence($object);
$end = $recurrence->end();
$this->assertSame($expected, $end ? $end->format('Y-m-d H:i:s') : $end);
}
/**
* kolab_date_recurrence::first_occurrence()
*
* @dataProvider data_first_occurrence
*/
function test_first_occurrence($recurrence_data, $start, $expected)
{
if (!kolab_format::supports(3)) {
$this->markTestSkipped('No Kolab support');
}
$start = new DateTime($start);
if (!empty($recurrence_data['UNTIL'])) {
$recurrence_data['UNTIL'] = new DateTime($recurrence_data['UNTIL']);
}
$event = array('start' => $start, 'recurrence' => $recurrence_data);
$object = kolab_format::factory('event', 3.0);
$object->set($event);
$recurrence = new kolab_date_recurrence($object);
$first = $recurrence->first_occurrence();
$this->assertEquals($expected, $first ? $first->format('Y-m-d H:i:s') : '');
}
/**
* kolab_date_recurrence::first_occurrence() for all-day events
*