Skip to content

Commit

Permalink
Merge pull request #192 from vever001/fix-all-day
Browse files Browse the repository at this point in the history
Fix attempt for Google and "All day".
  • Loading branch information
alies-dev authored Feb 19, 2024
2 parents 40514a0 + 293b8a6 commit 176efde
Show file tree
Hide file tree
Showing 14 changed files with 60 additions and 47 deletions.
14 changes: 6 additions & 8 deletions src/Generators/BaseOutlook.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,15 @@ public function generate(Link $link): string
{
$url = $this->baseUrl();

$dateTimeFormat = $link->allDay ? $this->dateFormat : $this->dateTimeFormat;

$utcStartDateTime = (clone $link->from)->setTimezone(new DateTimeZone('UTC'));
$utcEndDateTime = (clone $link->to)->setTimezone(new DateTimeZone('UTC'));

$url .= '&startdt='.$utcStartDateTime->format($dateTimeFormat);
$url .= '&enddt='.$utcEndDateTime->format($dateTimeFormat);

if ($link->allDay) {
$url .= '&startdt='.$link->from->format($this->dateFormat);
$url .= '&enddt='.$link->to->format($this->dateFormat);
$url .= '&allday=true';
}
else {
$url .= '&startdt='.(clone $link->from)->setTimezone(new DateTimeZone('UTC'))->format($this->dateTimeFormat);
$url .= '&enddt='.(clone $link->to)->setTimezone(new DateTimeZone('UTC'))->format($this->dateTimeFormat);
}

$url .= '&subject='.$this->sanitizeString($link->title);

Expand Down
16 changes: 3 additions & 13 deletions src/Generators/Google.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Google implements Generator
/** @var string {@see https://www.php.net/manual/en/function.date.php} */
protected $dateFormat = 'Ymd';
/** @var string */
protected $dateTimeFormat = 'Ymd\THis\Z';
protected $dateTimeFormat = 'Ymd\THis';

/** @psalm-var GoogleUrlParameters */
protected array $urlParameters = [];
Expand All @@ -31,19 +31,9 @@ public function generate(Link $link): string
{
$url = 'https://calendar.google.com/calendar/render?action=TEMPLATE';

$utcStartDateTime = (clone $link->from)->setTimezone(new DateTimeZone('UTC'));
$utcEndDateTime = (clone $link->to)->setTimezone(new DateTimeZone('UTC'));
$dateTimeFormat = $link->allDay ? $this->dateFormat : $this->dateTimeFormat;
$url .= '&dates='.$utcStartDateTime->format($dateTimeFormat).'/'.$utcEndDateTime->format($dateTimeFormat);

// Add timezone name if it is specified in both from and to dates and is the same for both
if (
$link->from->getTimezone() && $link->to->getTimezone()
&& $link->from->getTimezone()->getName() === $link->to->getTimezone()->getName()
) {
$url .= '&ctz=' . $link->from->getTimezone()->getName();
}

$url .= '&dates='.$link->from->format($dateTimeFormat).'/'.$link->to->format($dateTimeFormat);
$url .= '&ctz=' . $link->from->getTimezone()->getName();
$url .= '&text='.urlencode($link->title);

if ($link->description) {
Expand Down
32 changes: 16 additions & 16 deletions src/Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,20 @@ class Link

public function __construct(string $title, \DateTimeInterface $from, \DateTimeInterface $to, bool $allDay = false)
{
$this->from = clone $from;
$this->to = clone $to;
$this->title = $title;
$this->allDay = $allDay;

if ($from > $to) {
throw InvalidLink::negativeDateRange($from, $to);
// Ensures timezones match.
if ($this->from->getTimezone()->getName() !== $this->to->getTimezone()->getName()) {
$this->to->setTimezone($from->getTimezone());

Check failure on line 53 in src/Link.php

View workflow job for this annotation

GitHub Actions / psalm

UndefinedInterfaceMethod

src/Link.php:53:24: UndefinedInterfaceMethod: Method DateTimeInterface::setTimezone does not exist (see https://psalm.dev/181)
}

$this->from = clone $from;
$this->to = clone $to;
// Ensures from date is earlier than to date.
if ($this->from > $this->to) {
throw InvalidLink::negativeDateRange($from, $to);
}
}

/**
Expand All @@ -65,15 +70,15 @@ public function __construct(string $title, \DateTimeInterface $from, \DateTimeIn
*/
public static function create(string $title, \DateTimeInterface $from, \DateTimeInterface $to, bool $allDay = false)
{
// When creating all day events, we need to be in the UTC timezone as all day events are "floating" based on the user's timezone
if ($allDay) {
$startDate = new \DateTime($from->format('Y-m-d'), new \DateTimeZone('UTC'));
$numberOfDays = $from->diff($to)->days + 1;
$from_date = clone $from;
$to_date = clone $to;

return self::createAllDay($title, $startDate, $numberOfDays);
// If all day, we need to add 1 day to end date to get the correct duration.
if ($allDay) {
$to_date->modify('+1 day');
}

return new static($title, $from, $to, $allDay);
return new static($title, $from_date, $to_date, $allDay);

Check failure on line 81 in src/Link.php

View workflow job for this annotation

GitHub Actions / psalm

UnsafeInstantiation

src/Link.php:81:16: UnsafeInstantiation: Cannot safely instantiate class Spatie\CalendarLinks\Link with "new static" as its constructor might change in child classes (see https://psalm.dev/229)
}

/**
Expand All @@ -86,12 +91,7 @@ public static function create(string $title, \DateTimeInterface $from, \DateTime
*/
public static function createAllDay(string $title, \DateTimeInterface $fromDate, int $numberOfDays = 1): self
{
// In cases where the from date is not UTC, make sure it's UTC, size all day events are floating and non UTC dates cause bugs in the generators
if ($fromDate->getTimezone() !== new \DateTimeZone('UTC')) {
$fromDate = \DateTime::createFromFormat('Y-m-d', $fromDate->format('Y-m-d'));
}

$from = (clone $fromDate)->modify('midnight');
$from = (clone $fromDate);
$to = (clone $from)->modify("+$numberOfDays days");

Check failure on line 95 in src/Link.php

View workflow job for this annotation

GitHub Actions / psalm

UndefinedInterfaceMethod

src/Link.php:95:30: UndefinedInterfaceMethod: Method DateTimeInterface::modify does not exist (see https://psalm.dev/181)

return new self($title, $from, $to, true);
Expand Down
9 changes: 9 additions & 0 deletions tests/Generators/GoogleGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ public function it_correctly_generates_all_day_events_by_dates(): void
);
}

/** @test */

public function it_correctly_generates_all_day_events_by_dates_diff_tz(): void
{
$this->assertMatchesSnapshot(
$this->generator()->generate($this->createEventMultipleDaysViaStartEndWithDiffTimezoneLink())
);
}

/** @test */
public function it_can_generate_an_url_with_custom_parameters(): void
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20180201T090000Z/20180201T180000Z&ctz=UTC&text=Birthday+Party+%2B1&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog.%0AThere+will+be+line+breaks+on+it.%0AProject+link+%3Ca+href%3D%22https%3A%2F%2Fgithub.com%2Fspatie%2Fcalendar-links%22%3Ecalendar-links%3C%2Fa%3E%0A%3Cimg+src%3D%22https%3A%2F%2Fgithub-ads.s3.eu-central-1.amazonaws.com%2Fcalendar-links.jpg%3Ft%3D1%22+width%3D%22419px%22+%2F%3E%0A%3Cbr%3E%0AThank+you.%0A&location=Party+Lane+1A%2C+1337+Funtown
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20180201T090000/20180201T180000&ctz=UTC&text=Birthday+Party+%2B1&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog.%0AThere+will+be+line+breaks+on+it.%0AProject+link+%3Ca+href%3D%22https%3A%2F%2Fgithub.com%2Fspatie%2Fcalendar-links%22%3Ecalendar-links%3C%2Fa%3E%0A%3Cimg+src%3D%22https%3A%2F%2Fgithub-ads.s3.eu-central-1.amazonaws.com%2Fcalendar-links.jpg%3Ft%3D1%22+width%3D%22419px%22+%2F%3E%0A%3Cbr%3E%0AThank+you.%0A&location=Party+Lane+1A%2C+1337+Funtown
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191231T230000Z/20200101T010000Z&ctz=UTC&text=New+Year&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog&location=Party+Lane+1A%2C+1337+Funtown
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191231T230000/20200101T010000&ctz=UTC&text=New+Year&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog&location=Party+Lane+1A%2C+1337+Funtown
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20180201T090000Z/20180201T180000Z&ctz=UTC&text=Birthday&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog&location=Party+Lane+1A%2C+1337+Funtown
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20180201T090000/20180201T180000&ctz=UTC&text=Birthday&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog&location=Party+Lane+1A%2C+1337+Funtown
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20180201T090000Z/20180201T180000Z&ctz=UTC&text=Birthday&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog&location=Party+Lane+1A%2C+1337+Funtown&recur=RRULE%3AFREQ%3DDAILY
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20180201T090000/20180201T180000&ctz=UTC&text=Birthday&details=With+balloons%2C+clowns+and+stuff%0ABring+a+dog%2C+bring+a+frog&location=Party+Lane+1A%2C+1337+Funtown&recur=RRULE%3AFREQ%3DDAILY
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20240125/20240131&ctz=UTC&text=All+day+bugs&details=Testing+all+day
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20240125/20240131&ctz=Pacific/Wake&text=All+day+bugs&details=Testing+all+day
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20240125/20240201&ctz=Pacific/Wake&text=All+day+bugs&details=Testing+all+day
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20240125/20240130&ctz=UTC&text=All+day+bugs&details=Testing+all+day
https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20240125/20240130&ctz=Pacific/Wake&text=All+day+bugs&details=Testing+all+day
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ BEGIN:VCALENDAR
VERSION:2.0
PRODID:Spatie calendar-links
BEGIN:VEVENT
UID:8fe3eececcd6b020db3b47ef55e7cf89
UID:cb8469bae9cf10a9ee8f1179c6a932f5
SUMMARY:All day bugs
DTSTAMP:20240125
DTSTART:20240125
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ BEGIN:VCALENDAR
VERSION:2.0
PRODID:Spatie calendar-links
BEGIN:VEVENT
UID:a05fc4dac68ae6064aaae69dcdfd60a6
UID:b4be522f87b9894dadd2b9cd5479136b
SUMMARY:All day bugs
DTSTAMP:20240125
DTSTART:20240125
Expand Down
19 changes: 17 additions & 2 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected function createSingleDayAllDayEventLink(bool $immutable = false): Link

return Link::createAllDay(
'Birthday',
$dateTimeClass::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))
$dateTimeClass::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))->setTime(0, 0)
)->description($description)->address('Party Lane 1A, 1337 Funtown');
}

Expand All @@ -63,7 +63,7 @@ protected function createMultipleDaysAllDayEventLink(bool $immutable = false): L

return Link::createAllDay(
'Birthday',
$dateTimeClass::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC')),
$dateTimeClass::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))->setTime(0, 0),
5
)->description($description)->address('Party Lane 1A, 1337 Funtown');
}
Expand Down Expand Up @@ -95,6 +95,21 @@ protected function createEventMultipleDaysViaStartEndWithTimezoneLink(bool $immu
)->description($description);
}

protected function createEventMultipleDaysViaStartEndWithDiffTimezoneLink(bool $immutable = false): Link
{
$description = 'Testing all day';

$dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class;

// This should result in 7 days duration (2024-01-25 00:00 to 2024-01-31 00:00 Pacific/Wake).
return Link::create(
'All day bugs',
$dateTimeClass::createFromFormat('Y-m-d', '2024-01-25', new DateTimeZone('Pacific/Wake'))->setTime(0, 0),
$dateTimeClass::createFromFormat('Y-m-d', '2024-01-30', new DateTimeZone('Europe/Luxembourg'))->setTime(13, 00),
true,
)->description($description);
}

protected function createDescriptionIsHTMLcodeEventLink(bool $immutable = false): Link
{
$description = 'With balloons, clowns and stuff
Expand Down

0 comments on commit 176efde

Please sign in to comment.