diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 4a0c5a1..2d832ed 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -4,8 +4,7 @@ on: push: paths: - '**.php' - - 'psalm.xml' - - 'psalm.yml' + - 'psalm*' jobs: psalm: diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 1df62a1..6f4e5a4 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -37,7 +37,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, json, libxml, mbstring, pcre, reflection, spl, xml, xmlwriter coverage: none ini-values: assert.exception=1, zend.assertions=1 diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 5b9766d..276c398 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -6,13 +6,12 @@ __DIR__ . '/tests', ]) ->name('*.php') - ->notName('*.blade.php') ->ignoreDotFiles(true) ->ignoreVCS(true); return (new PhpCsFixer\Config()) ->setRules([ - '@PSR2' => true, + '@PSR12' => true, 'array_syntax' => ['syntax' => 'short'], 'ordered_imports' => ['sort_algorithm' => 'alpha'], 'no_unused_imports' => true, diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 795364c..b629420 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,63 +1,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - diff --git a/src/Exceptions/InvalidLink.php b/src/Exceptions/InvalidLink.php index 5eac383..0fe01de 100644 --- a/src/Exceptions/InvalidLink.php +++ b/src/Exceptions/InvalidLink.php @@ -1,5 +1,7 @@ format(self::DATETIME_FORMAT)}`) must be greater than FROM time (`{$from->format(self::DATETIME_FORMAT)}`)"); - } - public static function negativeDateRange(DateTimeInterface $from, DateTimeInterface $to): self { return new self("TO time (`{$to->format(self::DATETIME_FORMAT)}`) must be greater than FROM time (`{$from->format(self::DATETIME_FORMAT)}`)"); diff --git a/src/Generator.php b/src/Generator.php index 3ee0294..109cb53 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -1,13 +1,14 @@ */ abstract class BaseOutlook implements Generator { - /** @var string {@see https://www.php.net/manual/en/function.date.php} */ - protected $dateFormat = 'Y-m-d'; + /** @see https://www.php.net/manual/en/function.date.php */ + private const DATE_FORMAT = 'Y-m-d'; - /** @var string {@see https://www.php.net/manual/en/function.date.php} */ - protected $dateTimeFormat = 'Y-m-d\TH:i:s\Z'; + /** @see https://www.php.net/manual/en/function.date.php */ + private const DATETIME_FORMAT = 'Y-m-d\TH:i:s\Z'; /** @psalm-var OutlookUrlParameters */ protected array $urlParameters = []; + /** + * Get base URL for links. + * @return non-empty-string + */ + abstract protected function baseUrl(): string; + /** @psalm-param OutlookUrlParameters $urlParameters */ public function __construct(array $urlParameters = []) { $this->urlParameters = $urlParameters; } - /** Get base URL for links. */ - abstract public function baseUrl(): string; - - /** {@inheritDoc} */ + /** @inheritDoc */ public function generate(Link $link): string { $url = $this->baseUrl(); if ($link->allDay) { - $url .= '&startdt='.$link->from->format($this->dateFormat); - $url .= '&enddt='.$link->to->format($this->dateFormat); + $url .= '&startdt='.$link->from->format(self::DATE_FORMAT); + $url .= '&enddt='.$link->to->format(self::DATE_FORMAT); $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 .= '&startdt='.(clone $link->from)->setTimezone(new DateTimeZone('UTC'))->format(self::DATETIME_FORMAT); + $url .= '&enddt='.(clone $link->to)->setTimezone(new DateTimeZone('UTC'))->format(self::DATETIME_FORMAT); } $url .= '&subject='.$this->sanitizeString($link->title); diff --git a/src/Generators/Google.php b/src/Generators/Google.php index 3590593..ec3eb71 100644 --- a/src/Generators/Google.php +++ b/src/Generators/Google.php @@ -1,20 +1,23 @@ */ 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'; + /** @see https://www.php.net/manual/en/function.date.php */ + private const DATE_FORMAT = 'Ymd'; + + /** @see https://www.php.net/manual/en/function.date.php */ + private const DATETIME_FORMAT = 'Ymd\THis'; /** @psalm-var GoogleUrlParameters */ protected array $urlParameters = []; @@ -25,12 +28,15 @@ public function __construct(array $urlParameters = []) $this->urlParameters = $urlParameters; } - /** {@inheritDoc} */ + /** @var non-empty-string */ + protected const BASE_URL = 'https://calendar.google.com/calendar/render?action=TEMPLATE'; + + /** @inheritDoc */ public function generate(Link $link): string { - $url = 'https://calendar.google.com/calendar/render?action=TEMPLATE'; + $url = self::BASE_URL; - $dateTimeFormat = $link->allDay ? $this->dateFormat : $this->dateTimeFormat; + $dateTimeFormat = $link->allDay ? self::DATE_FORMAT : self::DATETIME_FORMAT; $url .= '&dates='.$link->from->format($dateTimeFormat).'/'.$link->to->format($dateTimeFormat); $url .= '&ctz=' . $link->from->getTimezone()->getName(); $url .= '&text='.urlencode($link->title); diff --git a/src/Generators/Ics.php b/src/Generators/Ics.php index 67fcc85..c39a993 100644 --- a/src/Generators/Ics.php +++ b/src/Generators/Ics.php @@ -1,5 +1,7 @@ presentationOptions = $presentationOptions; } - /** {@inheritDoc} */ + /** @inheritDoc */ public function generate(Link $link): string { $url = [ 'BEGIN:VCALENDAR', 'VERSION:2.0', // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.7.4 - 'PRODID:Spatie calendar-links', // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.7.3 + 'PRODID:'.($this->options['PRODID'] ?? 'Spatie calendar-links'), // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.7.3 'BEGIN:VEVENT', 'UID:'.($this->options['UID'] ?? $this->generateEventUid($link)), 'SUMMARY:'.$this->escapeString($link->title), @@ -86,11 +88,19 @@ public function generate(Link $link): string }; } + /** + * @param non-empty-list $propertiesAndComponents + * @return non-empty-string + */ protected function buildLink(array $propertiesAndComponents): string { return 'data:text/calendar;charset=utf8;base64,'.base64_encode(implode("\r\n", $propertiesAndComponents)); } + /** + * @param non-empty-list $propertiesAndComponents + * @return non-empty-string + */ protected function buildFile(array $propertiesAndComponents): string { return implode("\r\n", $propertiesAndComponents); diff --git a/src/Generators/WebOffice.php b/src/Generators/WebOffice.php index b52a7f6..2ec6caa 100644 --- a/src/Generators/WebOffice.php +++ b/src/Generators/WebOffice.php @@ -1,13 +1,16 @@ */ class Yahoo implements Generator { - /** @var string {@see https://www.php.net/manual/en/function.date.php} */ - protected $dateFormat = 'Ymd'; + /** @see https://www.php.net/manual/en/function.date.php */ + private const DATE_FORMAT = 'Ymd'; + + /** @see https://www.php.net/manual/en/function.date.php */ + private const DATETIME_FORMAT = 'Ymd\THis\Z'; - /** @var string */ - protected $dateTimeFormat = 'Ymd\THis\Z'; + /** @var non-empty-string */ + protected const BASE_URL = 'https://calendar.yahoo.com/?v=60&view=d&type=20'; + /** @inheritDoc */ /** @psalm-var YahooUrlParameters */ protected array $urlParameters = []; @@ -30,17 +36,17 @@ public function __construct(array $urlParameters = []) /** {@inheritDoc} */ public function generate(Link $link): string { - $url = 'https://calendar.yahoo.com/?v=60&view=d&type=20'; + $url = self::BASE_URL; - $dateTimeFormat = $link->allDay ? $this->dateFormat : $this->dateTimeFormat; + $dateTimeFormat = $link->allDay ? self::DATE_FORMAT : self::DATETIME_FORMAT; if ($link->allDay) { $url .= '&ST='.$link->from->format($dateTimeFormat); $url .= '&DUR=allday'; $url .= '&ET='.$link->to->format($dateTimeFormat); } else { - $utcStartDateTime = (clone $link->from)->setTimezone(new DateTimeZone('UTC')); - $utcEndDateTime = (clone $link->to)->setTimezone(new DateTimeZone('UTC')); + $utcStartDateTime = $link->from->setTimezone(new DateTimeZone('UTC')); + $utcEndDateTime = $link->to->setTimezone(new DateTimeZone('UTC')); $url .= '&ST='.$utcStartDateTime->format($dateTimeFormat); $url .= '&ET='.$utcEndDateTime->format($dateTimeFormat); } diff --git a/src/Link.php b/src/Link.php index acf665a..f1e7c28 100644 --- a/src/Link.php +++ b/src/Link.php @@ -1,5 +1,7 @@ from = clone $from; - $this->to = clone $to; $this->title = $title; $this->allDay = $allDay; // Ensures timezones match. - if ($this->from->getTimezone()->getName() !== $this->to->getTimezone()->getName()) { - $this->to->setTimezone($from->getTimezone()); + if ($from->getTimezone()->getName() !== $to->getTimezone()->getName()) { + $to = (clone $to)->setTimezone($from->getTimezone()); } + $this->from = \DateTimeImmutable::createFromInterface($from); + $this->to = \DateTimeImmutable::createFromInterface($to); + // Ensures from date is earlier than to date. if ($this->from > $this->to) { - throw InvalidLink::negativeDateRange($from, $to); + throw InvalidLink::negativeDateRange($this->from, $this->to); } } /** - * @param string $title - * @param \DateTimeInterface $from - * @param \DateTimeInterface $to - * @param bool $allDay - * - * @return static - * @throws InvalidLink + * @throws \Spatie\CalendarLinks\Exceptions\InvalidLink When date range is invalid. */ - public static function create(string $title, \DateTimeInterface $from, \DateTimeInterface $to, bool $allDay = false) + public static function create(string $title, \DateTimeInterface $from, \DateTimeInterface $to): static { - $from_date = clone $from; - $to_date = clone $to; - - // 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_date, $to_date, $allDay); + return new static($title, $from, $to); } /** - * @param string $title - * @param \DateTimeInterface|\DateTime|\DateTimeImmutable $fromDate - * @param int $numberOfDays - * - * @return Link - * @throws InvalidLink + * @param positive-int $numberOfDays + * @throws \Spatie\CalendarLinks\Exceptions\InvalidLink When date range is invalid. */ - public static function createAllDay(string $title, \DateTimeInterface $fromDate, int $numberOfDays = 1): self + public static function createAllDay(string $title, \DateTimeInterface $from, int $numberOfDays = 1): static { - $from = (clone $fromDate); $to = (clone $from)->modify("+$numberOfDays days"); + assert($to instanceof \DateTimeInterface); - return new self($title, $from, $to, true); + return new static($title, $from, $to, true); } - /** - * @param string $description - * - * @return $this - */ - public function description(string $description) + /** Set description of the Event. */ + public function description(string $description): static { $this->description = $description; return $this; } - /** - * @param string $address - * - * @return $this - */ - public function address(string $address) + /** Set the address of the Event. */ + public function address(string $address): static { $this->address = $address; @@ -134,8 +100,7 @@ public function google(array $urlParameters = []): string /** * @psalm-param IcsOptions $options ICS specific properties and components - * @param array $options ICS specific properties and components - * @param array{format?: \Spatie\CalendarLinks\Generators\Ics::FORMAT_*} $presentationOptions + * @psalm-param IcsPresentationOptions $presentationOptions * @return string */ public function ics(array $options = [], array $presentationOptions = []): string @@ -160,9 +125,4 @@ public function webOffice(array $urlParameters = []): string { return $this->formatWith(new WebOffice($urlParameters)); } - - public function __get($property) - { - return $this->$property; - } } diff --git a/tests/Generators/GeneratorTestContract.php b/tests/Generators/GeneratorTestContract.php index 69fdf1b..4b8eb70 100644 --- a/tests/Generators/GeneratorTestContract.php +++ b/tests/Generators/GeneratorTestContract.php @@ -1,5 +1,7 @@ assertMatchesSnapshot( $this->generator()->generate($this->createShortEventLink()) ); - - $this->assertSame( - $this->generator()->generate($this->createShortEventLink(false)), - $this->generator()->generate($this->createShortEventLink(true)) - ); } /** @test */ @@ -30,11 +27,6 @@ public function it_can_generate_a_single_day_allday_event_link(): void $this->assertMatchesSnapshot( $this->generator()->generate($this->createSingleDayAllDayEventLink()) ); - - $this->assertSame( - $this->generator()->generate($this->createSingleDayAllDayEventLink(false)), - $this->generator()->generate($this->createSingleDayAllDayEventLink(true)) - ); } /** @test */ @@ -43,11 +35,6 @@ public function it_can_generate_a_multiple_days_event_link(): void $this->assertMatchesSnapshot( $this->generator()->generate($this->createMultipleDaysEventLink()) ); - - $this->assertSame( - $this->generator()->generate($this->createMultipleDaysEventLink(false)), - $this->generator()->generate($this->createMultipleDaysEventLink(true)) - ); } /** @test */ @@ -56,23 +43,37 @@ public function it_can_generate_a_multiple_days_event_link_with_allday_flag(): v $this->assertMatchesSnapshot( $this->generator()->generate($this->createMultipleDaysAllDayEventLink()) ); + } - $this->assertSame( - $this->generator()->generate($this->createMultipleDaysAllDayEventLink(false)), - $this->generator()->generate($this->createMultipleDaysAllDayEventLink(true)) + /** @test */ + public function it_can_generate_a_description_is_html_code_event_link_with_allday_flag(): void + { + $this->assertMatchesSnapshot( + $this->generator()->generate($this->createDescriptionIsHtmlCodeEventLink()) ); } /** @test */ - public function it_can_generate_a_description_is_html_code_event_link_with_allday_flag(): void + public function it_correctly_generates_all_day_events_by_days(): void { $this->assertMatchesSnapshot( - $this->generator()->generate($this->createDescriptionIsHTMLcodeEventLink()) + $this->generator()->generate($this->createAllDayEventMultipleDaysWithTimezoneLink()) ); + } - $this->assertSame( - $this->generator()->generate($this->createDescriptionIsHTMLcodeEventLink(false)), - $this->generator()->generate($this->createDescriptionIsHTMLcodeEventLink(true)) + /** @test */ + public function it_correctly_generates_all_day_events_by_dates(): void + { + $this->assertMatchesSnapshot( + $this->generator()->generate($this->createEventMultipleDaysViaStartEndWithTimezoneLink()) + ); + } + + /** @test */ + public function it_correctly_generates_all_day_events_by_dates_diff_tz(): void + { + $this->assertMatchesSnapshot( + $this->generator()->generate($this->createEventMultipleDaysViaStartEndWithDiffTimezoneLink()) ); } } diff --git a/tests/Generators/GoogleGeneratorTest.php b/tests/Generators/GoogleGeneratorTest.php index 477b26f..8d5bc7c 100644 --- a/tests/Generators/GoogleGeneratorTest.php +++ b/tests/Generators/GoogleGeneratorTest.php @@ -1,12 +1,14 @@ assertMatchesSnapshot( - $this->generator()->generate($this->createAllDayEventMultipleDaysWithTimezoneLink()) - ); - } - - /** @test */ - public function it_correctly_generates_all_day_events_by_dates(): void - { - $this->assertMatchesSnapshot( - $this->generator()->generate($this->createEventMultipleDaysViaStartEndWithTimezoneLink()) - ); - } - - /** @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 { diff --git a/tests/Generators/IcsGeneratorTest.php b/tests/Generators/IcsGeneratorTest.php index d93f73f..f5b69be 100644 --- a/tests/Generators/IcsGeneratorTest.php +++ b/tests/Generators/IcsGeneratorTest.php @@ -1,5 +1,7 @@ assertMatchesSnapshot( - $this->generator(['UID' => 'random-uid', ['format' => Ics::FORMAT_FILE]])->generate($this->createShortEventLink()) - ); - } - - /** @test */ - public function it_has_a_product_id(): void + public function it_correctly_generates_all_day_events_by_days(): void { $this->assertMatchesSnapshot( - $this->generator(['PRODID' => 'Spatie calendar-links'], ['format' => Ics::FORMAT_FILE])->generate($this->createShortEventLink()) + $this->generator()->generate($this->createAllDayEventMultipleDaysWithTimezoneLink()) ); } /** @test */ - public function it_has_a_product_dtstamp(): void + public function it_correctly_generates_all_day_events_by_dates(): void { $this->assertMatchesSnapshot( - $this->generator(['DTSTAMP' => '20180201T090000Z'], ['format' => Ics::FORMAT_FILE])->generate($this->createShortEventLink()) + $this->generator()->generate($this->createEventMultipleDaysViaStartEndWithTimezoneLink()) ); } @@ -61,18 +61,18 @@ public function it_generates_base64_encoded_link_for_html(): void } /** @test */ - public function it_correctly_generates_all_day_events_by_days(): void + public function it_can_generate_an_ics_link_with_custom_uid(): void { $this->assertMatchesSnapshot( - $this->generator()->generate($this->createAllDayEventMultipleDaysWithTimezoneLink()) + $this->generator(['UID' => 'random-uid'])->generate($this->createShortEventLink()) ); } /** @test */ - public function it_correctly_generates_all_day_events_by_dates(): void + public function it_supports_custom_product_id(): void { $this->assertMatchesSnapshot( - $this->generator()->generate($this->createEventMultipleDaysViaStartEndWithTimezoneLink()) + $this->generator(['PRODID' => 'My Product'])->generate($this->createShortEventLink()) ); } diff --git a/tests/Generators/WebOfficeGeneratorTest.php b/tests/Generators/WebOfficeGeneratorTest.php index badfe9a..f4c7a23 100644 --- a/tests/Generators/WebOfficeGeneratorTest.php +++ b/tests/Generators/WebOfficeGeneratorTest.php @@ -1,12 +1,14 @@ description($description)->address('Party Lane 1A, 1337 Funtown'); } - protected function createMultipleDaysEventLink(bool $immutable = false): Link + protected function createMultipleDaysEventLink(): Link { $description = 'With balloons, clowns and stuff Bring a dog, bring a frog'; - $dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class; - return Link::create( 'New Year', - $dateTimeClass::createFromFormat('Y-m-d H:i', '2019-12-31 23:00', new DateTimeZone('UTC')), - $dateTimeClass::createFromFormat('Y-m-d H:i', '2020-01-01 1:00', new DateTimeZone('UTC')) + DateTime::createFromFormat('Y-m-d H:i', '2019-12-31 23:00', new DateTimeZone('UTC')), + DateTime::createFromFormat('Y-m-d H:i', '2020-01-01 1:00', new DateTimeZone('UTC')) )->description($description)->address('Party Lane 1A, 1337 Funtown'); } - protected function createSingleDayAllDayEventLink(bool $immutable = false): Link + protected function createSingleDayAllDayEventLink(): Link { $description = 'With balloons, clowns and stuff Bring a dog, bring a frog'; - $dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class; - return Link::createAllDay( 'Birthday', - $dateTimeClass::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))->setTime(0, 0) + DateTime::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))->setTime(0, 0) )->description($description)->address('Party Lane 1A, 1337 Funtown'); } - protected function createMultipleDaysAllDayEventLink(bool $immutable = false): Link + protected function createMultipleDaysAllDayEventLink(): Link { $description = 'With balloons, clowns and stuff Bring a dog, bring a frog'; - $dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class; return Link::createAllDay( 'Birthday', - $dateTimeClass::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))->setTime(0, 0), + DateTime::createFromFormat('Y-m-d', '2018-02-01', new DateTimeZone('UTC'))->setTime(0, 0), 5 )->description($description)->address('Party Lane 1A, 1337 Funtown'); } - protected function createAllDayEventMultipleDaysWithTimezoneLink(bool $immutable = false): Link + protected function createAllDayEventMultipleDaysWithTimezoneLink(): Link { $description = 'Testing all day'; - $dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class; - return Link::createAllDay( 'All day bugs', - $dateTimeClass::createFromFormat('Y-m-d', '2024-01-25', new DateTimeZone('Pacific/Wake'))->setTime(0, 0), + DateTime::createFromFormat('Y-m-d', '2024-01-25', new DateTimeZone('Pacific/Wake'))->setTime(0, 0), 5 )->description($description); } - protected function createEventMultipleDaysViaStartEndWithTimezoneLink(bool $immutable = false): Link + protected function createEventMultipleDaysViaStartEndWithTimezoneLink(): Link { $description = 'Testing all day'; - $dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class; - - return Link::create( + return Link::createAllDay( '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('Pacific/Wake'))->setTime(0, 0), - true, + \DateTime::createFromFormat('Y-m-d', '2024-01-25', new DateTimeZone('Pacific/Wake'))->setTime(0, 0), + 6, )->description($description); } - protected function createEventMultipleDaysViaStartEndWithDiffTimezoneLink(bool $immutable = false): Link + protected function createEventMultipleDaysViaStartEndWithDiffTimezoneLink(): 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( + return (new Link( '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), + DateTime::createFromFormat('Y-m-d', '2024-01-25', new DateTimeZone('Pacific/Wake'))->setTime(0, 0), + DateTime::createFromFormat('Y-m-d', '2024-01-30', new DateTimeZone('Europe/Luxembourg'))->setTime(13, 00), true, - )->description($description); + )); } - protected function createDescriptionIsHTMLcodeEventLink(bool $immutable = false): Link + protected function createDescriptionIsHtmlCodeEventLink(): Link { $description = 'With balloons, clowns and stuff Bring a dog, bring a frog. @@ -121,12 +106,10 @@ protected function createDescriptionIsHTMLcodeEventLink(bool $immutable = false) Thank you. '; - $dateTimeClass = $immutable ? DateTimeImmutable::class : DateTime::class; - return Link::create( 'Birthday Party +1', - $dateTimeClass::createFromFormat('Y-m-d H:i', '2018-02-01 09:00', new DateTimeZone('UTC')), - $dateTimeClass::createFromFormat('Y-m-d H:i', '2018-02-01 18:00', new DateTimeZone('UTC')) + DateTime::createFromFormat('Y-m-d H:i', '2018-02-01 09:00', new DateTimeZone('UTC')), + DateTime::createFromFormat('Y-m-d H:i', '2018-02-01 18:00', new DateTimeZone('UTC')) )->description($description)->address('Party Lane 1A, 1337 Funtown'); } }