Skip to content

Commit 5d1f81c

Browse files
authored
Merge pull request #47 from HiEventsDev/develop
Attach ICS calendar event to attendee ticket emails
2 parents c6cd50d + 3c725c6 commit 5d1f81c

File tree

8 files changed

+229
-4
lines changed

8 files changed

+229
-4
lines changed

backend/app/DomainObjects/EventSettingDomainObject.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,27 @@ public function getGetEmailFooterHtml(): string
2020
</div>
2121
HTML;
2222
}
23+
24+
public function getAddressString(): string
25+
{
26+
$locationDetails = $this->getLocationDetails();
27+
28+
if (is_null($locationDetails)) {
29+
return '';
30+
}
31+
32+
$addressParts = [
33+
$locationDetails['venue_name'] ?? null,
34+
$locationDetails['address_line_1'] ?? null,
35+
$locationDetails['address_line_2'] ?? null,
36+
$locationDetails['city'] ?? null,
37+
$locationDetails['state_or_region'] ?? null,
38+
$locationDetails['zip_or_postal_code'] ?? null,
39+
$locationDetails['country'] ?? null
40+
];
41+
42+
$filteredAddressParts = array_filter($addressParts, static fn($part) => !is_null($part) && $part !== '');
43+
44+
return implode(', ', $filteredAddressParts);
45+
}
2346
}

backend/app/Mail/Attendee/AttendeeTicketMail.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22

33
namespace HiEvents\Mail\Attendee;
44

5+
use Carbon\Carbon;
56
use HiEvents\DomainObjects\AttendeeDomainObject;
67
use HiEvents\DomainObjects\EventDomainObject;
78
use HiEvents\DomainObjects\EventSettingDomainObject;
9+
use HiEvents\DomainObjects\OrganizerDomainObject;
10+
use HiEvents\Helper\StringHelper;
811
use HiEvents\Helper\Url;
912
use HiEvents\Mail\BaseMail;
13+
use Illuminate\Mail\Mailables\Attachment;
1014
use Illuminate\Mail\Mailables\Content;
1115
use Illuminate\Mail\Mailables\Envelope;
1216
use Illuminate\Support\Str;
17+
use Spatie\IcalendarGenerator\Components\Calendar;
18+
use Spatie\IcalendarGenerator\Components\Event;
1319

1420
/**
1521
* @uses /backend/resources/views/emails/orders/attendee-ticket.blade.php
@@ -20,6 +26,7 @@ public function __construct(
2026
private readonly AttendeeDomainObject $attendee,
2127
private readonly EventDomainObject $event,
2228
private readonly EventSettingDomainObject $eventSettings,
29+
private readonly OrganizerDomainObject $organizer,
2330
)
2431
{
2532
parent::__construct();
@@ -51,4 +58,38 @@ public function content(): Content
5158
]
5259
);
5360
}
61+
62+
public function attachments(): array
63+
{
64+
$startDateTime = Carbon::parse($this->event->getStartDate(), $this->event->getTimezone());
65+
$endDateTime = $this->event->getEndDate() ? Carbon::parse($this->event->getEndDate(), $this->event->getTimezone()) : null;
66+
67+
$event = Event::create()
68+
->name($this->event->getTitle())
69+
->uniqueIdentifier('event-' . $this->attendee->getId())
70+
->startsAt($startDateTime)
71+
->url($this->event->getEventUrl())
72+
->organizer($this->organizer->getEmail(), $this->organizer->getName());
73+
74+
if ($this->event->getDescription()) {
75+
$event->description(StringHelper::previewFromHtml($this->event->getDescription()));
76+
}
77+
78+
if ($this->eventSettings->getLocationDetails()) {
79+
$event->address($this->eventSettings->getAddressString());
80+
}
81+
82+
if ($endDateTime) {
83+
$event->endsAt($endDateTime);
84+
}
85+
86+
$calendar = Calendar::create()
87+
->event($event)
88+
->get();
89+
90+
return [
91+
Attachment::fromData(static fn() => $calendar, 'event.ics')
92+
->withMime('text/calendar')
93+
];
94+
}
5495
}

backend/app/Services/Domain/Attendee/SendAttendeeTicketService.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use HiEvents\DomainObjects\AttendeeDomainObject;
66
use HiEvents\DomainObjects\EventDomainObject;
77
use HiEvents\DomainObjects\EventSettingDomainObject;
8+
use HiEvents\DomainObjects\OrganizerDomainObject;
89
use HiEvents\Mail\Attendee\AttendeeTicketMail;
910
use Illuminate\Contracts\Mail\Mailer;
1011

@@ -20,12 +21,14 @@ public function send(
2021
AttendeeDomainObject $attendee,
2122
EventDomainObject $event,
2223
EventSettingDomainObject $eventSettings,
24+
OrganizerDomainObject $organizer,
2325
): void
2426
{
2527
$this->mailer->to($attendee->getEmail())->send(new AttendeeTicketMail(
2628
attendee: $attendee,
2729
event: $event,
2830
eventSettings: $eventSettings,
31+
organizer: $organizer,
2932
));
3033
}
3134
}

backend/app/Services/Domain/Mail/SendOrderDetailsService.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ private function sendAttendeeTicketEmails(OrderDomainObject $order, EventDomainO
6262
continue;
6363
}
6464

65-
$this->sendAttendeeTicketService->send($attendee, $event, $event->getEventSettings());
65+
$this->sendAttendeeTicketService->send(
66+
attendee: $attendee,
67+
event: $event,
68+
eventSettings: $event->getEventSettings(),
69+
organizer: $event->getOrganizer(),
70+
);
71+
6672
$sentEmails[] = $attendee->getEmail();
6773
}
6874
}

backend/app/Services/Handlers/Attendee/ResendAttendeeTicketHandler.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
namespace HiEvents\Services\Handlers\Attendee;
44

55
use HiEvents\DomainObjects\EventSettingDomainObject;
6+
use HiEvents\DomainObjects\OrganizerDomainObject;
67
use HiEvents\DomainObjects\Status\AttendeeStatus;
78
use HiEvents\Exceptions\ResourceConflictException;
9+
use HiEvents\Repository\Eloquent\Value\Relationship;
810
use HiEvents\Repository\Interfaces\AttendeeRepositoryInterface;
911
use HiEvents\Repository\Interfaces\EventRepositoryInterface;
1012
use HiEvents\Services\Domain\Attendee\SendAttendeeTicketService;
@@ -42,10 +44,16 @@ public function handle(ResendAttendeeTicketDTO $resendAttendeeTicketDTO): void
4244
}
4345

4446
$event = $this->eventRepository
47+
->loadRelation(new Relationship(OrganizerDomainObject::class, name: 'organizer'))
4548
->loadRelation(EventSettingDomainObject::class)
4649
->findById($resendAttendeeTicketDTO->eventId);
4750

48-
$this->sendAttendeeTicketService->send($attendee, $event, $event->getEventSettings());
51+
$this->sendAttendeeTicketService->send(
52+
attendee: $attendee,
53+
event: $event,
54+
eventSettings: $event->getEventSettings(),
55+
organizer: $event->getOrganizer(),
56+
);
4957

5058
$this->logger->info('Attendee ticket resent', [
5159
'attendeeId' => $resendAttendeeTicketDTO->attendeeId,

backend/app/Services/Handlers/EventSettings/PartialUpdateEventSettingsHandler.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ public function handle(PartialUpdateEventSettingsDTO $eventSettingsDTO): EventSe
3131
throw new RefundNotPossibleException('Event settings not found');
3232
}
3333

34+
$locationDetails = $eventSettingsDTO->settings['location_details'] ?? $existingSettings->getLocationDetails();
35+
$isOnlineEvent = $eventSettingsDTO->settings['is_online_event'] ?? $existingSettings->getIsOnlineEvent();
36+
37+
if ($isOnlineEvent) {
38+
$locationDetails = null;
39+
}
40+
3441
return $this->eventSettingsHandler->handle(
3542
UpdateEventSettingsDTO::fromArray([
3643
'event_id' => $eventSettingsDTO->event_id,
@@ -59,7 +66,7 @@ public function handle(PartialUpdateEventSettingsDTO $eventSettingsDTO): EventSe
5966
'order_timeout_in_minutes' => $eventSettingsDTO->settings['order_timeout_in_minutes'] ?? $existingSettings->getOrderTimeoutInMinutes(),
6067
'website_url' => $eventSettingsDTO->settings['website_url'] ?? $existingSettings->getWebsiteUrl(),
6168
'maps_url' => $eventSettingsDTO->settings['maps_url'] ?? $existingSettings->getMapsUrl(),
62-
'location_details' => $eventSettingsDTO->settings['location_details'] ?? $existingSettings->getLocationDetails(),
69+
'location_details' => $locationDetails,
6370
'is_online_event' => $eventSettingsDTO->settings['is_online_event'] ?? $existingSettings->getIsOnlineEvent(),
6471
'online_event_connection_details' => array_key_exists('online_event_connection_details', $eventSettingsDTO->settings)
6572
? $eventSettingsDTO->settings['online_event_connection_details']

backend/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"maatwebsite/excel": "^3.1",
2020
"nette/php-generator": "^4.0",
2121
"php-open-source-saver/jwt-auth": "^2.1",
22+
"spatie/icalendar-generator": "^2.8",
2223
"stripe/stripe-php": "^10.15"
2324
},
2425
"require-dev": {

backend/composer.lock

Lines changed: 137 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)