Skip to content

Commit 641b6c9

Browse files
fix: Add sabre vobject rdate patch
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
1 parent a030dd6 commit 641b6c9

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

.patches/sabre-vobject-rdate.patch

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
From 099a37744a3aaf368bdd339f9c01e34553e8828e Mon Sep 17 00:00:00 2001
2+
From: SebastianKrupinski <krupinskis05@gmail.com>
3+
Date: Wed, 19 Nov 2025 19:19:32 -0500
4+
Subject: [PATCH] fix: use RDATE in time range check and use all instances
5+
6+
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
7+
---
8+
lib/Component/VEvent.php | 2 +-
9+
lib/Recur/EventIterator.php | 6 ++++-
10+
tests/VObject/Component/VEventTest.php | 35 ++++++++++++++++++++++++++
11+
3 files changed, 41 insertions(+), 2 deletions(-)
12+
13+
diff --git a/lib/Component/VEvent.php b/lib/Component/VEvent.php
14+
index e29e56322..6ca196d66 100644
15+
--- a/lib/Component/VEvent.php
16+
+++ b/lib/Component/VEvent.php
17+
@@ -41,7 +41,7 @@ class VEvent extends VObject\Component
18+
*/
19+
public function isInTimeRange(\DateTimeInterface $start, \DateTimeInterface $end): bool
20+
{
21+
- if ($this->RRULE) {
22+
+ if ($this->RRULE || $this->RDATE) {
23+
try {
24+
$it = new EventIterator($this, null, $start->getTimezone());
25+
} catch (NoInstancesException $e) {
26+
diff --git a/lib/Recur/EventIterator.php b/lib/Recur/EventIterator.php
27+
index 2c93bcf4e..79a070ee4 100644
28+
--- a/lib/Recur/EventIterator.php
29+
+++ b/lib/Recur/EventIterator.php
30+
@@ -164,8 +164,12 @@ public function __construct($input, ?string $uid = null, ?\DateTimeZone $timeZon
31+
}
32+
33+
if (isset($this->masterEvent->RDATE)) {
34+
+ $rdateValues = [];
35+
+ foreach ($this->masterEvent->RDATE as $rdate) {
36+
+ $rdateValues = array_merge($rdateValues, $rdate->getParts());
37+
+ }
38+
$this->recurIterator = new RDateIterator(
39+
- $this->masterEvent->RDATE->getParts(),
40+
+ $rdateValues,
41+
$this->startDate
42+
);
43+
} elseif (isset($this->masterEvent->RRULE)) {
44+
diff --git a/tests/VObject/Component/VEventTest.php b/tests/VObject/Component/VEventTest.php
45+
index 50fa626cc..5944ea574 100644
46+
--- a/tests/VObject/Component/VEventTest.php
47+
+++ b/tests/VObject/Component/VEventTest.php
48+
@@ -89,6 +89,41 @@ public function timeRangeTestData(): array
49+
$vevent9->RRULE = 'FREQ=DAILY';
50+
$tests[] = [$vevent9, new \DateTime('2016-10-31'), new \DateTime('2016-12-12'), true];
51+
52+
+ // Added this test to check events with RDATE property with multiple dates
53+
+ $vevent10 = clone $vevent;
54+
+ $vevent10->DTSTART = '20140901T000000Z';
55+
+ $vevent10->DTEND = '20140901T010000Z';
56+
+ $vevent10->add('RDATE', ['20141001T000000Z', '20141101T000000Z']);
57+
+ // DTSTART is the first occurrence
58+
+ $tests[] = [$vevent10, new \DateTime('2014-09-01'), new \DateTime('2014-09-02'), true];
59+
+ // RDATE adds additional occurrences on Oct 1 and Nov 1
60+
+ $tests[] = [$vevent10, new \DateTime('2014-10-01'), new \DateTime('2014-10-02'), true];
61+
+ $tests[] = [$vevent10, new \DateTime('2014-11-01'), new \DateTime('2014-11-02'), true];
62+
+ // No occurrence in December
63+
+ $tests[] = [$vevent10, new \DateTime('2014-12-01'), new \DateTime('2014-12-31'), false];
64+
+ // Range that includes first occurrence
65+
+ $tests[] = [$vevent10, new \DateTime('2014-08-01'), new \DateTime('2014-09-30'), true];
66+
+ // Range that spans all occurrences
67+
+ $tests[] = [$vevent10, new \DateTime('2014-08-01'), new \DateTime('2014-12-31'), true];
68+
+
69+
+ // Added this test to check events with RDATE property with multiple instances
70+
+ $vevent11 = clone $vevent;
71+
+ $vevent11->DTSTART = '20140901T000000Z';
72+
+ $vevent11->DTEND = '20140901T010000Z';
73+
+ $vevent11->add('RDATE', '20141001T000000Z');
74+
+ $vevent11->add('RDATE', '20141101T000000Z');
75+
+ // DTSTART is the first occurrence
76+
+ $tests[] = [$vevent11, new \DateTime('2014-09-01'), new \DateTime('2014-09-02'), true];
77+
+ // RDATE adds additional occurrences on Oct 1 and Nov 1
78+
+ $tests[] = [$vevent11, new \DateTime('2014-10-01'), new \DateTime('2014-10-02'), true];
79+
+ $tests[] = [$vevent11, new \DateTime('2014-11-01'), new \DateTime('2014-11-02'), true];
80+
+ // No occurrence in December
81+
+ $tests[] = [$vevent11, new \DateTime('2014-12-01'), new \DateTime('2014-12-31'), false];
82+
+ // Range that includes first occurrence
83+
+ $tests[] = [$vevent11, new \DateTime('2014-08-01'), new \DateTime('2014-09-30'), true];
84+
+ // Range that spans all occurrences
85+
+ $tests[] = [$vevent11, new \DateTime('2014-08-01'), new \DateTime('2014-12-31'), true];
86+
+
87+
return $tests;
88+
}
89+
}

composer.patches.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
},
77
"sabre/dav": {
88
"Check for instanceof INode instead of Node": ".patches/check-for-instanceof-INode-instead-of-Node-1595.patch"
9+
},
10+
"sabre/vobject": {
11+
"fix use RDATE in time range check and use all instances": ".patches/sabre-vobject-rdate.patch"
912
}
1013
}
1114
}

0 commit comments

Comments
 (0)