diff --git a/.patches/sabre-vobject-rdate.patch b/.patches/sabre-vobject-rdate.patch new file mode 100644 index 000000000..e18bf1bd4 --- /dev/null +++ b/.patches/sabre-vobject-rdate.patch @@ -0,0 +1,43 @@ +From 099a37744a3aaf368bdd339f9c01e34553e8828e Mon Sep 17 00:00:00 2001 +From: SebastianKrupinski +Date: Wed, 19 Nov 2025 19:19:32 -0500 +Subject: [PATCH] fix: use RDATE in time range check and use all instances + +Signed-off-by: SebastianKrupinski +--- + lib/Component/VEvent.php | 2 +- + lib/Recur/EventIterator.php | 6 ++++- + tests/VObject/Component/VEventTest.php | 35 ++++++++++++++++++++++++++ + 3 files changed, 41 insertions(+), 2 deletions(-) + +diff --git a/lib/Component/VEvent.php b/lib/Component/VEvent.php +index e29e56322..6ca196d66 100644 +--- a/lib/Component/VEvent.php ++++ b/lib/Component/VEvent.php +@@ -41,7 +41,7 @@ class VEvent extends VObject\Component + */ + public function isInTimeRange(\DateTimeInterface $start, \DateTimeInterface $end): bool + { +- if ($this->RRULE) { ++ if ($this->RRULE || $this->RDATE) { + try { + $it = new EventIterator($this, null, $start->getTimezone()); + } catch (NoInstancesException $e) { +diff --git a/lib/Recur/EventIterator.php b/lib/Recur/EventIterator.php +index 2c93bcf4e..79a070ee4 100644 +--- a/lib/Recur/EventIterator.php ++++ b/lib/Recur/EventIterator.php +@@ -164,8 +164,12 @@ public function __construct($input, ?string $uid = null, ?\DateTimeZone $timeZon + } + + if (isset($this->masterEvent->RDATE)) { ++ $rdateValues = []; ++ foreach ($this->masterEvent->RDATE as $rdate) { ++ $rdateValues = array_merge($rdateValues, $rdate->getParts()); ++ } + $this->recurIterator = new RDateIterator( +- $this->masterEvent->RDATE->getParts(), ++ $rdateValues, + $this->startDate + ); + } elseif (isset($this->masterEvent->RRULE)) { diff --git a/composer.patches.json b/composer.patches.json index ae985da3f..73fb07c30 100644 --- a/composer.patches.json +++ b/composer.patches.json @@ -6,6 +6,9 @@ }, "sabre/dav": { "Check for instanceof INode instead of Node": ".patches/check-for-instanceof-INode-instead-of-Node-1595.patch" + }, + "sabre/vobject": { + "fix use RDATE in time range check and use all instances": ".patches/sabre-vobject-rdate.patch" } } } diff --git a/sabre/vobject/PATCHES.txt b/sabre/vobject/PATCHES.txt new file mode 100644 index 000000000..9cc99e5bd --- /dev/null +++ b/sabre/vobject/PATCHES.txt @@ -0,0 +1,7 @@ +This file was automatically generated by Composer Patches (https://github.com/cweagans/composer-patches) +Patches applied to this directory: + +fix use RDATE in time range check and use all instances +Source: .patches/sabre-vobject-rdate.patch + + diff --git a/sabre/vobject/lib/Component/VEvent.php b/sabre/vobject/lib/Component/VEvent.php index 6ea93ed5e..a385a09e1 100644 --- a/sabre/vobject/lib/Component/VEvent.php +++ b/sabre/vobject/lib/Component/VEvent.php @@ -29,7 +29,7 @@ class VEvent extends VObject\Component */ public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end) { - if ($this->RRULE) { + if ($this->RRULE || $this->RDATE) { try { $it = new EventIterator($this, null, $start->getTimezone()); } catch (NoInstancesException $e) { diff --git a/sabre/vobject/lib/Recur/EventIterator.php b/sabre/vobject/lib/Recur/EventIterator.php index 55d6e4779..212c147d5 100644 --- a/sabre/vobject/lib/Recur/EventIterator.php +++ b/sabre/vobject/lib/Recur/EventIterator.php @@ -168,8 +168,12 @@ public function __construct($input, $uid = null, ?DateTimeZone $timeZone = null) } if (isset($this->masterEvent->RDATE)) { + $rdateValues = []; + foreach ($this->masterEvent->RDATE as $rdate) { + $rdateValues = array_merge($rdateValues, $rdate->getParts()); + } $this->recurIterator = new RDateIterator( - $this->masterEvent->RDATE->getParts(), + $rdateValues, $this->startDate ); } elseif (isset($this->masterEvent->RRULE)) {