From b082f423647c149d95a69ac2fc0fbe562897b29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=A4fer?= Date: Thu, 2 Mar 2023 13:35:33 +0100 Subject: [PATCH] Allow adding rrules as string --- README.md | 18 ++++++++++++++++++ src/Components/Event.php | 25 ++++++++++++++++++++++--- src/Properties/RRuleProperty.php | 2 +- tests/Components/EventTest.php | 9 +++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index facd631..7841cfe 100644 --- a/README.md +++ b/README.md @@ -527,6 +527,24 @@ Event::create('Laracon Online') ->doNotRepeatOn([new DateTime('05/16/2020 12:00:00'), new DateTime('08/13/2020 15:00:00')]); ``` +Alternatively you can add RRules as a string: + +```php +Event::create('SymfonyCon') + ->rruleAsString('FREQ=DAILY;INTERVAL=1'); +``` + +If you add RRules as a string the timezones included in DTSTART and UNTIL are unknown to the package as the string is never parsed and evaluated. If they are known you can add DTSTART and UNTIL separately to help the package discover the timezones: + +```php +Event::create('SymfonyCon') + ->rruleAsString( + 'DTSTART=20231207T090000Z;FREQ=DAILY;INTERVAL=1;UNTIL=20231208T090000Z', + new DateTime('7 december 2023 09:00:00', new DateTimeZone('UTC')), + new DateTime('8 december 2023 09:00:00', new DateTimeZone('UTC')) + ); +``` + ### Use with Laravel diff --git a/src/Components/Event.php b/src/Components/Event.php index be09af8..0f58b6a 100644 --- a/src/Components/Event.php +++ b/src/Components/Event.php @@ -70,7 +70,12 @@ class Event extends Component implements HasTimezones private ?EventStatus $status = null; - private ?RRule $rrule = null; + /** @var RRule|string|null */ + private $rrule = null; + + private ?DateTime $rruleStarting = null; + + private ?DateTime $rruleUntil = null; /** @var \Spatie\IcalendarGenerator\ValueObjects\DateTimeValue[] */ private array $recurrence_dates = []; @@ -295,6 +300,15 @@ public function rrule(RRule $rrule): Event return $this; } + public function rruleAsString(string $rrule, ?DateTimeInterface $starting = null, DateTimeInterface $until = null): Event + { + $this->rrule = $rrule; + $this->rruleStarting = $starting; + $this->rruleUntil = $until; + + return $this; + } + /** * @param DateTimeInterface[]|DateTimeInterface $dates * @param bool $withTime @@ -379,7 +393,10 @@ public function getTimezoneRangeCollection(): TimezoneRangeCollection ->add($this->starts) ->add($this->ends) ->add($this->created) - ->add($this->rrule) + ->add(is_string($this->rrule) + ? [$this->rruleStarting, $this->rruleUntil] + : $this->rrule + ) ->add($this->recurrence_dates) ->add($this->excluded_recurrence_dates); } @@ -441,7 +458,9 @@ private function resolveProperties(ComponentPayload $payload): self ) ->optional( $this->rrule, - fn () => RRuleProperty::create('RRULE', $this->rrule) + fn () => is_string($this->rrule) + ? TextProperty::create('RRULE', $this->rrule) + : RRuleProperty::create('RRULE', $this->rrule) ) ->multiple( $this->attendees, diff --git a/src/Properties/RRuleProperty.php b/src/Properties/RRuleProperty.php index 1642cc8..fa85391 100644 --- a/src/Properties/RRuleProperty.php +++ b/src/Properties/RRuleProperty.php @@ -32,6 +32,6 @@ public function getValue(): string public function getOriginalValue(): RRule { - return$this->recurrenceRule; + return $this->recurrenceRule; } } diff --git a/tests/Components/EventTest.php b/tests/Components/EventTest.php index 9b10bb1..19f8157 100644 --- a/tests/Components/EventTest.php +++ b/tests/Components/EventTest.php @@ -258,6 +258,15 @@ ->expectValue($rrule); }); +test('it an set a recurrence rule as a string', function () { + $payload = Event::create('An introduction into event sourcing') + ->rruleAsString($rrule = 'FREQ=DAILY;INTERVAL=2;UNTIL=20240301T230000Z') + ->resolvePayload(); + + PropertyExpectation::create($payload, 'RRULE') + ->expectValue($rrule); +}); + test('it can create an event without timezones', function () { $dateAlert = new DateTime('17 may 2019 11:00:00'); $dateStarts = new DateTime('17 may 2019 12:00:00');