Skip to content

Commit

Permalink
DEV-1283. Turned ical code into service that will generate a calendar…
Browse files Browse the repository at this point in the history
… from a name and a list of events.
  • Loading branch information
geoff-maddock committed Dec 21, 2024
1 parent c4b6e13 commit 7b8b544
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 186 deletions.
54 changes: 0 additions & 54 deletions app/Http/Controllers/Api/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -570,60 +570,6 @@ public function delete(int $id, Request $request)
return back();
}

/**
* Return the users events in iCal format.
*
* @return Response|RedirectResponse|string
*/
public function ical(int $id, Request $request)
{
// check if there is a logged in user
if (!$this->user) {
flash()->error('Error', 'No user is logged in.');

return back();
}

if (!$user = User::find($id)) {
flash()->error('Error', 'No such user');

return back();
}
define('ICAL_FORMAT', 'Ymd\THis\Z');

// create a calendar object
$vCalendar = new Calendar($this->user->getFullNameAttribute().' Calendar');

// add the following response
// get the next x events they are attending
$events = $user->getAttendingFuture()->take(self::DEFAULT_SHOW_COUNT);

// loop over events
foreach ($events as $event) {
$venue = $event->venue ? $event->venue->name : '';

$vEvent = new Event();
$vEvent
->setDtStart($event->start_at)
->setDtEnd($event->end_at)
->setDtStamp($event->created_at)
->setSummary($event->name)
->setDescription($event->description)
->setUniqueId($event->id)
->setLocation($venue)
->setModified($event->updated_at)
->setStatus('CONFIRMED')
->setUrl($event->primary_link);

$vCalendar->addComponent($vEvent);
}

// Set the headers
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');

return $vCalendar->render();
}

/**
* @return RedirectResponse|Response
Expand Down
102 changes: 4 additions & 98 deletions app/Http/Controllers/EventsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,7 @@
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\UploadedFile;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Eluceo\iCal\Domain\Entity\Calendar;
use Eluceo\iCal\Domain\Entity\Event as iCalEvent;
use Eluceo\iCal\Domain\ValueObject\Organizer;
use Eluceo\iCal\Domain\ValueObject\Uri;
use Eluceo\iCal\Domain\ValueObject\EmailAddress;
use Eluceo\iCal\Domain\ValueObject\Location;
use Eluceo\iCal\Domain\ValueObject\UniqueIdentifier;
use Eluceo\iCal\Presentation\Factory\CalendarFactory;
use Eluceo\iCal\Domain\ValueObject\TimeSpan;
use Eluceo\iCal\Domain\ValueObject\DateTime;
use Eluceo\iCal\Domain\ValueObject\Attachment;

use App\Services\Calendar\CalBuilder;


class EventsController extends Controller
Expand Down Expand Up @@ -208,6 +197,7 @@ public function indexIcal(
Request $request,
ListParameterSessionStore $listParamSessionStore,
ListEntityResultBuilder $listEntityResultBuilder,
CalBuilder $iCalBuilder
)
{

Expand Down Expand Up @@ -247,93 +237,9 @@ public function indexIcal(
->paginate($listResultSet->getLimit());

// create a calendar object
$vCalendar = new Calendar([]);

// loop over events
foreach ($events as $event) {
// use the route for the event as the unique id
$uniqueId = route('events.show', ['event' => $event]);

// set up unique ID
$uniqueIdentifier = new UniqueIdentifier($uniqueId);

$vEvent = new iCalEvent($uniqueIdentifier);

// set up occurrence
$start = new DateTime($event->start_at, false);
$end = $event->end_at ? new DateTime($event->end_at, false) : null;
$occurrence = new TimeSpan($start, $end ? $end : $start);

$vEvent->setOccurrence($occurrence)
->setSummary($event->name)
->setDescription($event->description);

// convert $event->updated_at to timestamp
$updated = new DateTime($event->updated_at, false);
$vEvent->touch($updated);

// set the url
$url = $event->primary_link ? $event->primary_link : $uniqueId;
$url = new Uri($url);
$vEvent->setUrl($url);

// set up the venue location
// get the name for the venue or set to empty
$venue = $event->venue ? $event->venue->name : '';

// set the location
if ($venue) {
$vEvent->setLocation(new Location($venue));
}

// get the promoter to set organizer
if ($event->promoter) {
// check for contacts on the promoter
if ($event->promoter->contacts->count() > 0) {

// cycle through all contacts to find one with an email address
foreach ($event->promoter->contacts as $contact) {
if ($contact->email) {

$organizer = new Organizer(
new EmailAddress('[email protected]'),
$event->promoter->name,
new Uri('ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)'),
new EmailAddress('[email protected]')
);

$vEvent->setOrganizer($organizer);

break;
}
}
}
}

// add the primary image as a url attachment
$photo = $event->getPrimaryPhoto();
if ($photo) {
$imageUrl = Storage::disk('external')->url($photo->getStoragePath());

$urlAttachment = new Attachment(
new Uri($imageUrl),
'image/jpeg'
);

$vEvent->addAttachment($urlAttachment);
}

$vCalendar->addEvent($vEvent);
}

$componentFactory = new CalendarFactory();
$calendarComponent = $componentFactory->createCalendar($vCalendar);

// Set the headers
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="arcane-city-ical.ics"');
$calendar = $iCalBuilder->buildCalendar('arcane-city-ical.ics', $events);

return $calendarComponent;
return $calendar;
}


Expand Down
42 changes: 8 additions & 34 deletions app/Http/Controllers/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@
use App\Mail\WeeklyUpdate;
use App\Models\Activity;
use App\Models\Group;
use App\Models\Photo;
use App\Models\Profile;
use App\Models\User;
use App\Models\UserStatus;
use App\Models\Visibility;
use App\Services\ImageHandler;
use App\Services\SessionStore\ListParameterSessionStore;
use Carbon\Carbon;
use Eluceo\iCal\Component\Calendar;
use Eluceo\iCal\Component\Event;
use Exception;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
Expand All @@ -30,7 +27,7 @@
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use App\Services\Calendar\CalBuilder;
use Throwable;

class UsersController extends Controller
Expand Down Expand Up @@ -605,7 +602,10 @@ public function delete(int $id, Request $request)
*
* @return Response|RedirectResponse|string
*/
public function ical(int $id, Request $request)
public function ical(
int $id,
Request $request,
CalBuilder $iCalBuilder)
{
// check if there is a logged in user
if (!$this->user) {
Expand All @@ -619,40 +619,14 @@ public function ical(int $id, Request $request)

return back();
}
define('ICAL_FORMAT', 'Ymd\THis\Z');

// create a calendar object
$vCalendar = new Calendar($this->user->getFullNameAttribute().' Calendar');

// add the following response
// get the next x events they are attending
$events = $user->getAttendingFuture()->take(self::DEFAULT_SHOW_COUNT);

// loop over events
foreach ($events as $event) {
$venue = $event->venue ? $event->venue->name : '';

$vEvent = new Event();
$vEvent
->setDtStart($event->start_at)
->setDtEnd($event->end_at)
->setDtStamp($event->created_at)
->setSummary($event->name)
->setDescription($event->description)
->setUniqueId($event->id)
->setLocation($venue)
->setModified($event->updated_at)
->setStatus('CONFIRMED')
->setUrl($event->primary_link);

$vCalendar->addComponent($vEvent);
}

// Set the headers
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');
// create a calendar object
$calendar = $iCalBuilder->buildCalendar($this->user->getFullNameAttribute().' Calendar', $events);

return $vCalendar->render();
return $calendar;
}

/**
Expand Down
123 changes: 123 additions & 0 deletions app/Services/Calendar/CalBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

namespace App\Services\Calendar;

use App\Models\Event;
use Eluceo\iCal\Domain\Entity\Calendar;
use Eluceo\iCal\Domain\Entity\Event as iCalEvent;
use Eluceo\iCal\Domain\ValueObject\Organizer;
use Eluceo\iCal\Domain\ValueObject\Uri;
use Eluceo\iCal\Domain\ValueObject\EmailAddress;
use Eluceo\iCal\Domain\ValueObject\Location;
use Eluceo\iCal\Domain\ValueObject\UniqueIdentifier;
use Eluceo\iCal\Presentation\Factory\CalendarFactory;
use Eluceo\iCal\Domain\ValueObject\TimeSpan;
use Eluceo\iCal\Domain\ValueObject\DateTime;
use Eluceo\iCal\Domain\ValueObject\Attachment;
use Storage;


/**
* Builds and exports ical calendar
*/
class CalBuilder
{

/**
* Build iCal calendar from events
* @param string $calendarName Name of the calendar file
* @param $events Array of Event models
* @return string The iCal formatted calendar
*/
public function buildCalendar(string $calendarName = "event-tracker.ics", $events): string

Check failure on line 32 in app/Services/Calendar/CalBuilder.php

View workflow job for this annotation

GitHub Actions / build

Deprecated in PHP 8.0: Required parameter $events follows optional parameter $calendarName.
{
// create a calendar object
$vCalendar = new Calendar([]);

// loop over events
foreach ($events as $event) {
// use the route for the event as the unique id
$uniqueId = route('events.show', ['event' => $event]);

// set up unique ID
$uniqueIdentifier = new UniqueIdentifier($uniqueId);

$vEvent = new iCalEvent($uniqueIdentifier);

// set up occurrence
$start = new DateTime($event->start_at, false);
$end = $event->end_at ? new DateTime($event->end_at, false) : null;
$occurrence = new TimeSpan($start, $end ? $end : $start);

$vEvent->setOccurrence($occurrence)
->setSummary($event->name)
->setDescription($event->description);

// convert $event->updated_at to timestamp
$updated = new DateTime($event->updated_at, false);
$vEvent->touch($updated);

// set the url
$url = $event->primary_link ? $event->primary_link : $uniqueId;
$url = new Uri($url);
$vEvent->setUrl($url);

// set up the venue location
// get the name for the venue or set to empty
$venue = $event->venue ? $event->venue->name : '';

// set the location
if ($venue) {
$vEvent->setLocation(new Location($venue));
}

// get the promoter to set organizer
if ($event->promoter) {
// check for contacts on the promoter
if ($event->promoter->contacts->count() > 0) {

// cycle through all contacts to find one with an email address
foreach ($event->promoter->contacts as $contact) {
if ($contact->email) {

$organizer = new Organizer(
new EmailAddress($contact->email),
$event->promoter->name,
new Uri($uniqueId),
new EmailAddress($contact->email)
);

$vEvent->setOrganizer($organizer);

break;
}
}
}
}

// add the primary image as a url attachment
$photo = $event->getPrimaryPhoto();
if ($photo) {
$imageUrl = Storage::disk('external')->url($photo->getStoragePath());

$urlAttachment = new Attachment(
new Uri($imageUrl),
'image/jpeg'
);

$vEvent->addAttachment($urlAttachment);
}

$vCalendar->addEvent($vEvent);
}

$componentFactory = new CalendarFactory();
$calendarComponent = $componentFactory->createCalendar($vCalendar);

// Set the headers
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="'.$calendarName.'"');

return $calendarComponent;
}
}

0 comments on commit 7b8b544

Please sign in to comment.