Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,10 @@ Tag pair that returns the next X event dates.

### Download Links

Single Tag returns a url to the event data and add it to your calendar. If there's a "location" field (see config above), it'll get added to the download.
Single Tag returns a url to the event data and add it to your calendar. The following fields will be added to the ICS if they exist:
* `location` (see config above)
* `description`
* `link`

Parameters:

Expand Down
3 changes: 2 additions & 1 deletion src/Http/Controllers/IcsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public function __invoke(Request $request)

if ($entry) {
return $this->downloadIcs(
EventFactory::createFromEntry($entry)->toICalendarEvents()
EventFactory::createFromEntry($entry)->toICalendarEvents(),
$entry->title
);
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/Types/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,18 @@ public function toICalendarEvent(string|CarbonInterface $date): ?ICalendarEvent
->startsAt($immutableDate->setTimeFromTimeString($this->startTime()))
->endsAt($immutableDate->setTimeFromTimeString($this->endTime()));

if ($location = $this->location($this->event)) {
if (!is_null($location = $this->location($this->event))) {
$iCalEvent->address($location);
}

if (!is_null($description = $this->event->description)) {
$iCalEvent->description($description);
}

if (!is_null($link = $this->event->link)) {
$iCalEvent->url($link);
}

return $iCalEvent;
}

Expand Down
18 changes: 16 additions & 2 deletions src/Types/MultiDayEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,24 @@ public function toICalendarEvent(string|CarbonInterface $date): ?ICalendarEvent
$immutableDate = $this->toCarbonImmutable($date);
$day = $this->getDayFromDate($immutableDate);

return ICalendarEvent::create($this->event->title)
$iCalEvent = ICalendarEvent::create($this->event->title)
->uniqueIdentifier($this->event->id())
->startsAt($immutableDate->setTimeFromTimeString($day->start()))
->endsAt($immutableDate->setTimeFromTimeString($day->end()));

if (! is_null($location = $this->location($this->event))) {
$iCalEvent->address($location);
}

if (! is_null($description = $this->event->description)) {
$iCalEvent->description($description);
}

if (! is_null($link = $this->event->link)) {
$iCalEvent->url($link);
}

return $iCalEvent;
}

/**
Expand All @@ -87,7 +101,7 @@ protected function rule(bool $collapseDays = false): RRuleInterface
}

return tap(
new RSet(),
new RSet,
fn (RSet $rset) => $this->days->each(fn (Day $day) => $rset->addRRule([
'count' => 1,
'dtstart' => $day->end()->subSecond(),
Expand Down
28 changes: 19 additions & 9 deletions src/Types/RecurringEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,25 @@ public function interval(): int
*/
public function toICalendarEvents(): array
{
$timezone = $this->timezone['timezone'];

return [
ICalendarEvent::create($this->event->title)
->uniqueIdentifier($this->event->id())
->startsAt($this->start())
->endsAt($this->end())
->rrule($this->spatieRule()),
];
$iCalEvent = ICalendarEvent::create($this->event->title)
->uniqueIdentifier($this->event->id())
->startsAt($this->start())
->endsAt($this->end())
->rrule($this->spatieRule());

if (! is_null($location = $this->location($this->event))) {
$iCalEvent->address($location);
}

if (! is_null($description = $this->event->description)) {
$iCalEvent->description($description);
}

if (! is_null($link = $this->event->link)) {
$iCalEvent->url($link);
}

return [$iCalEvent];
}

protected function rule(): RRuleInterface
Expand Down
83 changes: 82 additions & 1 deletion tests/Feature/IcsControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ protected function setUp(): void
'start_time' => '11:00',
'end_time' => '12:00',
'location' => 'The Location',
'description' => 'The description',
'link' => 'https://transformstudios.com'
])->save();
}

Expand All @@ -38,6 +40,8 @@ public function can_create_single_day_event_ics_file()

$this->assertStringContainsString('DTSTART:'.now()->setTimeFromTimeString('11:00')->format('Ymd\THis'), $response->streamedContent());
$this->assertStringContainsString('LOCATION:The Location', $response->streamedContent());
$this->assertStringContainsString('DESCRIPTION:The description', $response->streamedContent());
$this->assertStringContainsString('URL:https://transformstudios.com', $response->streamedContent());
}

#[Test]
Expand All @@ -55,6 +59,9 @@ public function can_create_single_day_recurring_event_ics_file()
'start_time' => '11:00',
'end_time' => '12:00',
'recurrence' => 'weekly',
'location' => 'The Location',
'description' => 'The description',
'link' => 'https://transformstudios.com'
])->save();

$response = $this->get(route('statamic.events.ics.show', [
Expand All @@ -63,25 +70,95 @@ public function can_create_single_day_recurring_event_ics_file()
]))->assertDownload('recurring-event.ics');

$this->assertStringContainsString('DTSTART:'.now()->setTimeFromTimeString('11:00')->format('Ymd\THis'), $response->streamedContent());
$this->assertStringContainsString('LOCATION:The Location', $response->streamedContent());
$this->assertStringContainsString('DESCRIPTION:The description', $response->streamedContent());
$this->assertStringContainsString('URL:https://transformstudios.com', $response->streamedContent());

$this->get(route('statamic.events.ics.show', [
'date' => now()->addDay()->toDateString(),
'event' => 'the-recurring-id',
]))->assertStatus(404);
}

#[Test]
public function can_create_ics_with_single_date_recurrence()
{
Carbon::setTestNow(now()->addDay()->setTimeFromTimeString('10:00'));

Entry::make()
->collection('events')
->slug('recurring-event')
->id('the-recurring-id')
->data([
'title' => 'Recurring Event',
'start_date' => Carbon::now()->toDateString(),
'start_time' => '11:00',
'end_time' => '12:00',
'recurrence' => 'weekly',
'location' => 'The Location',
'description' => 'The description',
'link' => 'https://transformstudios.com'
])->save();

$response = $this->get(route('statamic.events.ics.show', [
'date' => now()->toDateString(),
'event' => 'the-recurring-id',
]))->assertDownload('recurring-event.ics');


$this->assertStringContainsString('DTSTART:'.now()->setTimeFromTimeString('11:00')->format('Ymd\THis'), $response->streamedContent());
$this->assertStringContainsString('LOCATION:The Location', $response->streamedContent());
$this->assertStringContainsString('DESCRIPTION:The description', $response->streamedContent());
$this->assertStringContainsString('URL:https://transformstudios.com', $response->streamedContent());

}

#[Test]
public function can_create_ics_with_recurrence()
{
Carbon::setTestNow(now()->addDay()->setTimeFromTimeString('10:00'));

Entry::make()
->collection('events')
->slug('recurring-event')
->id('the-recurring-id')
->data([
'title' => 'Recurring Event',
'start_date' => Carbon::now()->toDateString(),
'start_time' => '11:00',
'end_time' => '12:00',
'recurrence' => 'weekly',
'location' => 'The Location',
'description' => 'The description',
'link' => 'https://transformstudios.com'
])->save();

$response = $this->get(route('statamic.events.ics.show', [
'event' => 'the-recurring-id',
]))->assertDownload('recurring-event.ics');

$this->assertStringContainsString('DTSTART:'.now()->setTimeFromTimeString('11:00')->format('Ymd\THis'), $response->streamedContent());
$this->assertStringContainsString('LOCATION:The Location', $response->streamedContent());
$this->assertStringContainsString('DESCRIPTION:The description', $response->streamedContent());
$this->assertStringContainsString('URL:https://transformstudios.com', $response->streamedContent());

}

#[Test]
public function can_create_single_day_multiday_event_ics_file()
{
Carbon::setTestNow(now());

$entry = Entry::make()
Entry::make()
->slug('multi-day-event')
->collection('events')
->id('the-multi-day-event')
->data([
'title' => 'Multi-day Event',
'multi_day' => true,
'location' => 'The Location',
'description' => 'The description',
'link' => 'https://transformstudios.com',
'days' => [
[
'date' => now()->toDateString(),
Expand Down Expand Up @@ -112,6 +189,10 @@ public function can_create_single_day_multiday_event_ics_file()
]))->assertDownload('multi-day-event.ics');

$this->assertStringContainsString('DTSTART:'.now()->addDay()->setTimeFromTimeString('11:00')->format('Ymd\THis'), $response->streamedContent());
$this->assertStringContainsString('LOCATION:The Location', $response->streamedContent());
$this->assertStringContainsString('DESCRIPTION:The description', $response->streamedContent());
$this->assertStringContainsString('URL:https://transformstudios.com', $response->streamedContent());

}

#[Test]
Expand Down