Skip to content

Commit

Permalink
Merge branch 'master' of github.com:fruux/sabre-vobject
Browse files Browse the repository at this point in the history
  • Loading branch information
evert committed Oct 23, 2015
2 parents 265405a + a1d975e commit 9a0f531
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 7 deletions.
20 changes: 19 additions & 1 deletion CHANGELOG.md
@@ -1,14 +1,25 @@
ChangeLog
=========

4.0.0-alpha2 (2015-??-??)
4.0.0-alpha3 (????-??-??)
-------------------------

* #258: Support for expanding events that use `RDATE`. (@jabdoa2)
* #258: Correctly support TZID for events that use `RDATE`. (@jabdoa2)


4.0.0-alpha2 (2015-09-04)
-------------------------

* Updated windows timezone file to support new mexican timezone.
* #239: Added a `BirthdayCalendarGenerator`. (@DominikTo)
* #250: `isInTimeRange()` now considers the timezone for floating dates and
times. (@armin-hackmann)
* Added a duplicate vcard merging tool for the command line.
* #253: `isInTimeRange()` now correctly handles events that throw the
`NoInstancesException` exception. (@migrax, @DominikTo)
* #254: The parser threw an `E_NOTICE` for certain invalid objects. It now
correctly throws a `ParseException`.


4.0.0-alpha1 (2015-07-17)
Expand Down Expand Up @@ -46,6 +57,13 @@ ChangeLog
and `IntegerValue` to allow PHP 7 compatibility.


3.4.7 (2015-09-04)
------------------

* #253: Handle `isInTimeRange` for recurring events that have 0 valid
instances. (@DominikTo, @migrax).


3.4.6 (2015-08-06)
------------------

Expand Down
7 changes: 7 additions & 0 deletions lib/BirthdayCalendarGenerator.php
Expand Up @@ -120,6 +120,13 @@ function getResult() {
continue;
}

// We've seen clients (ez-vcard) putting "BDAY:" properties
// without a value into vCards. If we come across those, we'll
// skip them.
if (empty($object->BDAY->getValue())) {
continue;
}

// We're always converting to vCard 4.0 so we can rely on the
// VCardConverter handling the X-APPLE-OMIT-YEAR property for us.
$object = $object->convert(Document::VCARD40);
Expand Down
2 changes: 1 addition & 1 deletion lib/Component/VCalendar.php
Expand Up @@ -310,7 +310,7 @@ function expand(DateTimeInterface $start, DateTimeInterface $end, DateTimeZone $
throw new \LogicException('Event did not have a UID!');
}

if (isset($vevent->{'RECURRENCE-ID'}) || isset($vevent->RRULE)) {
if (isset($vevent->{'RECURRENCE-ID'}) || isset($vevent->RRULE) || isset($vevent->{'RDATE'})) {
if (isset($recurringEvents[$uid])) {
$recurringEvents[$uid][] = $vevent;
} else {
Expand Down
15 changes: 14 additions & 1 deletion lib/Component/VEvent.php
Expand Up @@ -5,6 +5,7 @@
use DateTimeInterface;
use Sabre\VObject;
use Sabre\VObject\Recur\EventIterator;
use Sabre\VObject\Recur\NoInstancesException;

/**
* VEvent component.
Expand Down Expand Up @@ -32,7 +33,19 @@ class VEvent extends VObject\Component {
function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end) {

if ($this->RRULE) {
$it = new EventIterator($this, null, $start->getTimezone());

try {

$it = new EventIterator($this, null, $start->getTimezone());

} catch (NoInstancesException $e) {

// If we've catched this exception, there are no instances
// for the event that fall into the specified time-range.
return false;

}

$it->fastForward($start);

// We fast-forwarded to a spot where the end-time of the
Expand Down
2 changes: 1 addition & 1 deletion lib/FreeBusyData.php
Expand Up @@ -92,7 +92,7 @@ function add($start, $end, $type) {
if ($this->data[$insertStartIndex - 1]['start'] === $start) {
// The old item starts at the exact same point as the new item.
$insertStartIndex--;
}
}

// Now we know where to insert the item, we need to know where it
// starts overlapping with items on the tail end. We need to start
Expand Down
3 changes: 3 additions & 0 deletions lib/Parser/MimeDir.php
Expand Up @@ -344,6 +344,9 @@ protected function readProperty($line) {

$value = $this->unescapeParam($value);

if (is_null($lastParam)) {
throw new ParseException('Invalid Mimedir file. Line starting at ' . $this->startLine . ' did not follow iCalendar/vCard conventions');
}
if (is_null($property['parameters'][$lastParam])) {
$property['parameters'][$lastParam] = $value;
} elseif (is_array($property['parameters'][$lastParam])) {
Expand Down
4 changes: 3 additions & 1 deletion lib/Property/ICalendar/Recur.php
Expand Up @@ -51,6 +51,9 @@ function setValue($value) {
if (strpos($v, ',') !== false) {
$v = explode(',', $v);
}
if (strcmp($k, 'until') === 0) {
$v = strtr($v, [':' => '', '-' => '']);
}
} else {
$v = array_map('strtoupper', $v);
}
Expand Down Expand Up @@ -91,7 +94,6 @@ function getValue() {
* Sets a multi-valued property.
*
* @param array $parts
*
* @return void
*/
function setParts(array $parts) {
Expand Down
3 changes: 2 additions & 1 deletion lib/Recur/RDateIterator.php
Expand Up @@ -91,7 +91,8 @@ function next() {

$this->currentDate =
DateTimeParser::parse(
$this->dates[$this->counter - 1]
$this->dates[$this->counter - 1],
$this->startDate->getTimezone()
);

}
Expand Down
2 changes: 1 addition & 1 deletion lib/Version.php
Expand Up @@ -14,6 +14,6 @@ class Version {
/**
* Full version number.
*/
const VERSION = '4.0.0-alpha2';
const VERSION = '4.0.0-alpha3';

}
29 changes: 29 additions & 0 deletions tests/VObject/BirthdayCalendarGeneratorTest.php
Expand Up @@ -414,6 +414,35 @@ function testVcardStringWithValidBirthdayLocalized() {

}

function testVcardStringWithEmptyBirthdayProperty() {

$generator = new BirthdayCalendarGenerator();
$input = <<<VCF
BEGIN:VCARD
VERSION:3.0
N:Gump;Forrest;;Mr.
FN:Forrest Gump
BDAY:
UID:foo
END:VCARD
VCF;

$expected = <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
END:VCALENDAR
ICS;

$generator->setObjects($input);
$output = $generator->getResult();

$this->assertVObjEquals(
$expected,
$output
);

}

/**
* @expectedException \Sabre\VObject\ParseException
*/
Expand Down
10 changes: 10 additions & 0 deletions tests/VObject/Component/VEventTest.php
Expand Up @@ -71,6 +71,16 @@ function timeRangeTestData() {
$tests[] = [$vevent7, new \DateTime('2012-02-01 15:00:00'), new \DateTime('2012-02-02'), true];
// The timezone of timerange in question should also be considered.
$tests[] = [$vevent7, new \DateTime('2012-02-02 00:00:00', new \DateTimeZone('Europe/Berlin')), new \DateTime('2012-02-03 00:00:00', new \DateTimeZone('Europe/Berlin')), false];

// Added this test to check recurring events that have no instances.
$vevent8 = clone $vevent;
$vevent8->DTSTART = '20130329T140000';
$vevent8->DTEND = '20130329T153000';
$vevent8->RRULE = ['FREQ' => 'WEEKLY', 'BYDAY' => ['FR'], 'UNTIL' => '20130412T115959Z'];
$vevent8->add('EXDATE', '20130405T140000');
$vevent8->add('EXDATE', '20130329T140000');
$tests[] = [$vevent8, new \DateTime('2013-03-01'), new \DateTime('2013-04-01'), false];

return $tests;

}
Expand Down
21 changes: 21 additions & 0 deletions tests/VObject/Issue259Test.php
@@ -0,0 +1,21 @@
<?php

namespace Sabre\VObject;

class Issue259Test extends \PHPUnit_Framework_TestCase {

function testParsingJcalWithUntil() {
$jcalWithUntil = '["vcalendar",[],[["vevent",[["uid",{},"text","dd1f7d29"],["organizer",{"cn":"robert"},"cal-address","mailto:robert@robert.com"],["dtstart",{"tzid":"Europe/Berlin"},"date-time","2015-10-21T12:00:00"],["dtend",{"tzid":"Europe/Berlin"},"date-time","2015-10-21T13:00:00"],["transp",{},"text","OPAQUE"],["rrule",{},"recur",{"freq":"MONTHLY","until":"2016-01-01T22:00:00Z"}]],[]]]]';
$parser = new Parser\Json();
$parser->setInput($jcalWithUntil);

$vcalendar = $parser->parse();
$eventAsArray = $vcalendar->select('VEVENT');
$event = reset($eventAsArray);
$rruleAsArray = $event->select('RRULE');
$rrule = reset($rruleAsArray);
$this->assertNotNull($rrule);
$this->assertEquals($rrule->getValue(), 'FREQ=MONTHLY;UNTIL=20160101T220000Z');
}

}
30 changes: 30 additions & 0 deletions tests/VObject/IssueUndefinedIndexTest.php
@@ -0,0 +1,30 @@
<?php

namespace Sabre\VObject;

class IssueUndefinedIndexTest extends \PHPUnit_Framework_TestCase {

/**
* @expectedException \Sabre\VObject\ParseException
*/
function testRead() {

$input = <<<VCF
BEGIN:VCARD
VERSION:3.0
PRODID:foo
N:Holmes;Sherlock;;;
FN:Sherlock Holmes
ORG:Acme Inc;
ADR;type=WORK;type=pref:;;,
\\n221B,Baker Street;London;;12345;United Kingdom
UID:foo
END:VCARD
VCF;

$vcard = Reader::read($input, Reader::OPTION_FORGIVING);
$this->assertInstanceOf('Sabre\\VObject\\Component\\VCard', $vcard);

}

}
59 changes: 59 additions & 0 deletions tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php
@@ -0,0 +1,59 @@
<?php

namespace Sabre\VObject;

use DateTime;
use DateTimeImmutable;
use DateTimeZone;

/**
* This is a unittest for Issue #53.
*/
class HandleRDateExpandTest extends \PHPUnit_Framework_TestCase {

function testExpand() {

$input = <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:2CD5887F7CF4600F7A3B1F8065099E40-240BDA7121B61224
DTSTAMP;VALUE=DATE-TIME:20151014T110604Z
CREATED;VALUE=DATE-TIME:20151014T110245Z
LAST-MODIFIED;VALUE=DATE-TIME:20151014T110541Z
DTSTART;VALUE=DATE-TIME;TZID=Europe/Berlin:20151012T020000
DTEND;VALUE=DATE-TIME;TZID=Europe/Berlin:20151012T013000
SUMMARY:Test
SEQUENCE:2
RDATE;VALUE=DATE-TIME;TZID=Europe/Berlin:20151015T020000,20151017T020000,20
151018T020000,20151020T020000
TRANSP:OPAQUE
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR
ICS;

$vcal = Reader::read($input);
$this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);

$vcal->expand(new DateTime('2015-01-01'), new DateTime('2015-12-01'));

$result = iterator_to_array($vcal->vevent);

$this->assertEquals(5, count($result));

$utc = new DateTimeZone('UTC');
$expected = array(
new DateTimeImmutable("2015-10-12", $utc),
new DateTimeImmutable("2015-10-15", $utc),
new DateTimeImmutable("2015-10-17", $utc),
new DateTimeImmutable("2015-10-18", $utc),
new DateTimeImmutable("2015-10-20", $utc),
);

$result = array_map(function($ev){return $ev->dtstart->getDateTime();}, $result);
$this->assertEquals($expected, $result);

}

}
24 changes: 24 additions & 0 deletions tests/VObject/Recur/RDateIteratorTest.php
Expand Up @@ -27,6 +27,30 @@ function testSimple() {

}

function testTimezone() {

$tz = new DateTimeZone('Europe/Berlin');
$it = new RDateIterator('20140901T000000,20141001T000000', new DateTimeImmutable('2014-08-01 00:00:00', $tz));

$expected = [
new DateTimeImmutable('2014-08-01 00:00:00', $tz),
new DateTimeImmutable('2014-09-01 00:00:00', $tz),
new DateTimeImmutable('2014-10-01 00:00:00', $tz),
];

$result = iterator_to_array($it);

$this->assertEquals(
$expected,
iterator_to_array($it)
);


$this->assertFalse($it->isInfinite());

}


function testFastForward() {

$utc = new DateTimeZone('UTC');
Expand Down

0 comments on commit 9a0f531

Please sign in to comment.